1.理解朴素贝叶斯

1)基本概念

  • 依据概率原则进行分类。如天气预测概率。
  • 朴素贝叶斯(Naive Bayes, NB)适合场景:为估计一个结果的概率,从众多属性中提取的信息应该被同时考虑。
  • 很多算法忽略了弱影响的特征(若有大量弱影响的特征,它们组合在一起的影响可能会很大),但NB算法利用了所有可以获得的证据来修正预测。
  • 贝叶斯方法的基本概念:事件,试验,概率,联合概率,独立事件,相关事件(建立预测模型的基础),条件概率,先验概率,似然概率,边际似然概率,后验概率,频率表
  • 条件概率公式(事件B已经发生的条件下,事件A发生的概率):

  • 后验概率(如商业垃圾邮件过滤器:判断viagra是垃圾邮件spam的概率):

2)朴素贝叶斯算法

  • NB优点:简单快速有效;能处理噪音及缺失值数据;训练集不限大小;容易获得估计概率值。
  • NB缺点:依赖同样重要和独立的特征(错误假设);应用在大量数值特征的数据集中不理想;概率估计值比预测的类更不可靠。
  • “朴素”的含义:基于这样一个假设:数据集的所有特征都具有相同的重要性和独立性,但在大多数实际应用中,假设不成立。
  • 朴素贝叶斯算法具通用性和准确性,在分类学习任务中很强大。

①朴素贝叶斯分类

假设有4个单词的100封邮件的似然表来训练朴素贝叶斯算法(如下表),收到新邮件时(包含了单词viagra和unsubscribe,但不包含money和groceries),通过计算后验概率来判断它是否为垃圾邮件。



原始的基于贝叶斯定理的后验概率:



将4个单词事件视为独立事件(类条件独立),可简化公式:



计算垃圾邮件总似然为:

计算非垃圾邮件总似然为:

是垃圾邮件的概率为:

②拉普拉斯估计

对于类中一个或多个水平,如果一个时间从没有发生过,那它出现的概率为0,从而导致后验概率值也为0(抵消或否决了所有其他的证据)。

比如,这次的新邮件中包含了前述的4个单词,则计算垃圾邮件的似然:

该邮件是垃圾邮件的概率为:

拉普拉斯估计就是给频率表中每个计数加上一个很小的数(一般设为1),保证每一类中每个特征发生的概率是非零的。

拉普拉斯估计后的垃圾邮件似然:

③数值型特征值离散化

前面的频率表要求特征必须为分类变量,如果是数值变量,需要将数值离散化(分段),如根据时间寻找分割点。如果没有明显的分割点,也可利用分位数进行分段。

但将数值特征离散化总是会导致信息量的减少,因为特征的原始粒度减少为几个数目较少的类别。分段太少会导致重要趋势被掩盖,分段太多会导致频率表中的计数值很小,因此需要平衡分段数。

2.朴素贝斯分类应用

示例:基于贝叶斯算法的手机垃圾短信过滤。

1)收集数据

数据下载sms_spam.csv

链接: https://pan.baidu.com/s/1fAufKXCSufwd8It_DHXyWQ 提取码: vgyj

2)探索和准备数据

## Example: Filtering spam SMS messages ----
## Step 2: Exploring and preparing the data ---- # read the sms data into the sms data frame
sms_raw <- read.csv("sms_spam.csv", stringsAsFactors = FALSE) # examine the structure of the sms data
str(sms_raw) # convert spam/ham to factor.
sms_raw$type <- factor(sms_raw$type) # examine the type variable more carefully
str(sms_raw$type)
table(sms_raw$type)

处理和分析文本数据

文本挖掘包tm创建语料库(文本集合),inspect函数查看语料库内容,tm_map函数转换tm语料库(如去数字,变小写等),stopwords函数去除填充词(如to/and/or/but等)。

清理完后标记分解单词形成的组,并创建稀疏矩阵。再进行训练集和测试集划分,并利用词云进行可视化文本数据。最后为高频词创建指示特征。

PS:运行过程中tm包的tolower参数一直报错,未解决,因此本示例最终没有用此参数。


# build a corpus using the text mining (tm) package
library(tm)
sms_corpus <- VCorpus(VectorSource(sms_raw$text)) # examine the sms corpus
print(sms_corpus)
inspect(sms_corpus[1:2]) as.character(sms_corpus[[1]])
lapply(sms_corpus[1:2], as.character) # clean up the corpus using tm_map()
# sms_corpus_clean <- tm_map(sms_corpus, content_transformer(tolower)) #Error
sms_corpus_clean <- sms_corpus # show the difference between sms_corpus and corpus_clean
as.character(sms_corpus[[1]])
as.character(sms_corpus_clean[[1]]) sms_corpus_clean <- tm_map(sms_corpus_clean, removeNumbers) # remove numbers
sms_corpus_clean <- tm_map(sms_corpus_clean, removeWords, stopwords()) # remove stop words
sms_corpus_clean <- tm_map(sms_corpus_clean, removePunctuation) # remove punctuation # tip: create a custom function to replace (rather than remove) punctuation
removePunctuation("hello...world")
replacePunctuation <- function(x) { gsub("[[:punct:]]+", " ", x) }
replacePunctuation("hello...world") # illustration of word stemming
library(SnowballC)
wordStem(c("learn", "learned", "learning", "learns")) sms_corpus_clean <- tm_map(sms_corpus_clean, stemDocument) sms_corpus_clean <- tm_map(sms_corpus_clean, stripWhitespace) # eliminate unneeded whitespace # examine the final clean corpus
lapply(sms_corpus[1:3], as.character)
lapply(sms_corpus_clean[1:3], as.character) # create a document-term sparse matrix
sms_dtm <- DocumentTermMatrix(sms_corpus_clean) # alternative solution: create a document-term sparse matrix directly from the SMS corpus
sms_dtm2 <- DocumentTermMatrix(sms_corpus, control = list(
# tolower = TRUE, #注释掉也报错
removeNumbers = TRUE,
stopwords = TRUE,
removePunctuation = TRUE,
stemming = TRUE
)) # alternative solution: using custom stop words function ensures identical result
sms_dtm3 <- DocumentTermMatrix(sms_corpus, control = list(
# tolower = TRUE, #注释掉也报错
removeNumbers = TRUE,
stopwords = function(x) { removeWords(x, stopwords()) },
removePunctuation = TRUE,
stemming = TRUE
)) # compare the result
sms_dtm
sms_dtm2
sms_dtm3 # creating training and test datasets
sms_dtm_train <- sms_dtm[1:4169, ]
sms_dtm_test <- sms_dtm[4170:5558, ] # also save the labels
sms_train_labels <- sms_raw[1:4169, ]$type
sms_test_labels <- sms_raw[4170:5558, ]$type # check that the proportion of spam is similar
prop.table(table(sms_train_labels))
prop.table(table(sms_test_labels)) # word cloud visualization
library(wordcloud)
wordcloud(sms_corpus_clean, min.freq = 50, random.order = FALSE) # subset the training data into spam and ham groups
spam <- subset(sms_raw, type == "spam")
ham <- subset(sms_raw, type == "ham") wordcloud(spam$text, max.words = 40, scale = c(3, 0.5))
wordcloud(ham$text, max.words = 40, scale = c(3, 0.5)) sms_dtm_freq_train <- removeSparseTerms(sms_dtm_train, 0.999)
sms_dtm_freq_train # indicator features for frequent words
findFreqTerms(sms_dtm_train, 5) # save frequently-appearing terms to a character vector
sms_freq_words <- findFreqTerms(sms_dtm_train, 5)
str(sms_freq_words) # create DTMs with only the frequent terms
sms_dtm_freq_train <- sms_dtm_train[ , sms_freq_words]
sms_dtm_freq_test <- sms_dtm_test[ , sms_freq_words] # convert counts to a factor
convert_counts <- function(x) {
x <- ifelse(x > 0, "Yes", "No")
} # apply() convert_counts() to columns of train/test data
sms_train <- apply(sms_dtm_freq_train, MARGIN = 2, convert_counts)
sms_test <- apply(sms_dtm_freq_test, MARGIN = 2, convert_counts)

得到的sms_trainsms_test的单词稀疏矩阵如下表所示:

3)训练模型

上例已经将原始短信转换为可以用一个统计模型代表的形式,因此用NB算法根据单词的存在与否来估计一条给定的短信是垃圾短信的概率。

使用e1071::naiveBays()klaR::NaiveBayes()函数。

## Step 3: Training a model on the data ----
library(e1071)
sms_classifier <- naiveBayes(sms_train, sms_train_labels)

4)评估模型性能

基于测试集中的未知短信来检验分类器的预测值。比较预测值和真实值,仍然通过混淆矩阵来计算。

## Step 4: Evaluating model performance ----
sms_test_pred <- predict(sms_classifier, sms_test) library(gmodels)
CrossTable(sms_test_pred, sms_test_labels,
prop.chisq = FALSE, prop.t = FALSE, prop.r = FALSE,
dnn = c('predicted', 'actual'))

没怎么处理效果也比较好,所以NB是文本分类的一种标准算法。同样地,假阴性问题带来的代价较大(把正常短信过滤掉了),进一步提升模型性能试试。

5)提升模型性能

上面训练时,没有设置拉普拉斯估计,此处设为1,性能有所提升。

## Step 5: Improving model performance ----
sms_classifier2 <- naiveBayes(sms_train,
sms_train_labels,
laplace = 1) #拉普拉斯估计值 sms_test_pred2 <- predict(sms_classifier2, sms_test)
CrossTable(sms_test_pred2, sms_test_labels,
prop.chisq = FALSE, prop.t = FALSE, prop.r = FALSE,
dnn = c('predicted', 'actual'))


机器学习与R语言系列推文汇总:

【机器学习与R语言】1-机器学习简介

【机器学习与R语言】2-K近邻(kNN)

【机器学习与R语言】3-朴素贝叶斯(NB)

【机器学习与R语言】4-决策树

【机器学习与R语言】5-规则学习

【机器学习与R语言】6-线性回归

【机器学习与R语言】7-回归树和模型树

【机器学习与R语言】8-神经网络

【机器学习与R语言】9-支持向量机

【机器学习与R语言】10-关联规则

【机器学习与R语言】11-Kmeans聚类

【机器学习与R语言】12-如何评估模型的性能?

【机器学习与R语言】13-如何提高模型的性能?

【机器学习与R语言】3-概率学习朴素贝叶斯(NB)的更多相关文章

  1. R语言︱贝叶斯网络语言实现及与朴素贝叶斯区别(笔记)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 一.贝叶斯网络与朴素贝叶斯的区别 朴素贝叶斯的 ...

  2. 【机器学习速成宝典】模型篇05朴素贝叶斯【Naive Bayes】(Python版)

    目录 先验概率与后验概率 条件概率公式.全概率公式.贝叶斯公式 什么是朴素贝叶斯(Naive Bayes) 拉普拉斯平滑(Laplace Smoothing) 应用:遇到连续变量怎么办?(多项式分布, ...

  3. Stanford大学机器学习公开课(六):朴素贝叶斯多项式模型、神经网络、SVM初步

    (一)朴素贝叶斯多项式事件模型 在上篇笔记中,那个最基本的NB模型被称为多元伯努利事件模型(Multivariate Bernoulli Event Model,以下简称 NB-MBEM).该模型有多 ...

  4. 机器学习Matlab打击垃圾邮件的分类————朴素贝叶斯模型

    该系列来自于我<人工智能>课程回顾总结,以及实验的一部分进行了总结学习机 垃圾分类是有监督的学习分类最经典的案例,本文首先回顾了概率论的基本知识.则以及朴素贝叶斯模型的思想.最后给出了垃圾 ...

  5. 机器学习Sklearn系列:(四)朴素贝叶斯

    3--朴素贝叶斯 原理 朴素贝叶斯本质上就是通过贝叶斯公式来对得到类别概率,但区别于通常的贝叶斯公式,朴素贝叶斯有一个默认条件,就是特征之间条件独立. 条件概率公式: \[P(B|A) = \frac ...

  6. 【Spark机器学习速成宝典】模型篇04朴素贝叶斯【Naive Bayes】(Python版)

    目录 朴素贝叶斯原理 朴素贝叶斯代码(Spark Python) 朴素贝叶斯原理 详见博文:http://www.cnblogs.com/itmorn/p/7905975.html 返回目录 朴素贝叶 ...

  7. 机器学习之朴素贝叶斯&贝叶斯网络

    贝叶斯决决策论       在所有相关概率都理想的情况下,贝叶斯决策论考虑基于这些概率和误判损失来选择最优标记,基本思想如下: (1)已知先验概率和类条件概率密度(似然) (2)利用贝叶斯转化为后验概 ...

  8. 100天搞定机器学习|Day15 朴素贝叶斯

    Day15,开始学习朴素贝叶斯,先了解一下贝爷,以示敬意. 托马斯·贝叶斯 (Thomas Bayes),英国神学家.数学家.数理统计学家和哲学家,1702年出生于英国伦敦,做过神甫:1742年成为英 ...

  9. 吴裕雄--天生自然python机器学习:朴素贝叶斯算法

    分类器有时会产生错误结果,这时可以要求分类器给出一个最优的类别猜测结果,同 时给出这个猜测的概率估计值. 概率论是许多机器学习算法的基础 在计算 特征值取某个值的概率时涉及了一些概率知识,在那里我们先 ...

随机推荐

  1. Linux上传下载神器之 lrzsz

    在开发的过程中,经常遇到 需要在 Linux 和 Windows 之间上传下载文件的情况 这时,一般都是使用 FTP 或者 WinSCP 工具进行上传下载, 虽然也能解决问题,但是这些工具需要在本地安 ...

  2. maven编码 gbk 的不可映射字符

    解决这个问题的思路: 在maven的编译插件中声明正确的字符集编码编码--编译使用的字符集编码与代码文件使用的字符集编码一致!! 安装系统之后,一般中文系统默认字符集是GBK.我们安装的软件一般都继承 ...

  3. 使用cerebro可视化ElasticSearch集群信息

    使用cerebro可视化ElasticSearch集群信息 一.背景 二.安装步骤 1.下载并解压 2.配置cerebro 3.启动 cerebro 4.启动界面 三.注意事项 四.参考文档 一.背景 ...

  4. elasticsearch使用ik中文分词器

    elasticsearch使用ik中文分词器 一.背景 二.安装 ik 分词器 1.从 github 上找到和本次 es 版本匹配上的 分词器 2.使用 es 自带的插件管理 elasticsearc ...

  5. csp总结 (差点爆零的总结)

    T1,iterator忘了怎么写了,想了很久都想不出来有什么可以替代,只好O(n^2): T2,不会,只会打暴力 T3,自以为是正解,写了很久大概3h,却一直过不了大样例,大样例输出全是0: T4,不 ...

  6. 2021.9.7考试总结[NOIP模拟49]

    T1 Reverse $BFS$暴力$O(n^2)$ 过程中重复枚举了很多点,考虑用链表记录当前点后面可到达的第一个未更新点. 搜索时枚举翻转子串的左端点,之后便可以算出翻转后$1$的位置. $cod ...

  7. Python import cStringIO ImportError: No module named 'cStringIO'

    From Python 3.0 changelog; The StringIO and cStringIO modules are gone. Instead, import the io modul ...

  8. Java中Lambda表达式的进化之路

    Lambda表达式的进化之路 为什么要使用Lambda表达式 可以简洁代码,提高代码的可读性 可以避免匿名内部类定义过多导致逻辑紊乱 在原先实现接口抽象方法的时候,需要通过定义一个实现接口的外部类来实 ...

  9. 中文NER的那些事儿4. 数据增强在NER的尝试

    这一章我们不聊模型来聊聊数据,解决实际问题时90%的时间其实都是在和数据作斗争,于是无标注,弱标注,少标注,半标注对应的各类解决方案可谓是百花齐放.在第二章我们也尝试通过多目标对抗学习的方式引入额外的 ...

  10. Forest v1.5.12 发布,声明式 HTTP 框架,已超过 1.6k star

    Forest介绍 Forest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL.Header 以及 Body 等信息)绑定到您自定义的 Interfac ...