1. 简介
垃圾邮件有一些共同的特征,尤其表现在一系列词汇上,有监督的机器学习通过从大量预标注的预料中分别学习垃圾邮件额正常邮件的用词频率,从而对新邮件预测分类。
表达文本的向量有两种代表性的向量:1.词频向量 2.tf-idf向量
2. NLP 文本特征向量化
使用停用词
停用词是像 "and"、"the"、”him" 这样的词,这些词在表示文本内容时被认为是没有信息的,无意义的,在邮件分类问题上作用微乎其微,可以删除它们,然而,有时类似的词对预测很有用,比如在对写作风格或性格进行分类时。
在选择停用词时应当尽可能地谨慎,流行的停止词列表可能包括对某些任务(如计算机)具有高度信息性的词。
同时还应该确保停止单词列表具有与矢量化器中使用的相同的预处理和标记。
词袋模型
tf-idf
哈希向量化文本
3. Logistic 回归 二分类
算法评价
4. 朴素贝叶斯
以下参考自 《机器学习实战》[美] Peter Harrington
对于社区留言分类:侮辱性,非侮辱性
基于概率论的分类方法:朴素贝叶斯
要求分类器给出一个最优的类别猜测结果,同时给出这个猜测的概率估计值。
之所以称之为 “朴素”,
是因为整个形式化过程只做最原始、最简单的假设
基于贝叶斯决策理论的分类方法
朴素贝叶斯
优点:在数据较少的情况下仍然 有效,可以处理多类别问题。 缺点:对于输入数据的准备方式较为敏感。
适用数据类型:标称型数据。
朴素贝叶斯是贝叶斯决策理论的一部分

我们现在用 \(p1(x,y)\) 表示数据点 \((x,y)\) 属于类别1(图中用圆点表示的类别)的概率,
用 \(p2(x,y)\) 表示数据点 \((x,y)\) 属于类别2(图中用三角形表示的类别)的概率,
那么对于一个新数据点 \((x,y)\) ,可以用下面的规则来判断它的类别:
- 若
p1(x,y) > p2(x,y)
,那么类别为1 - 若
p2(x,y) > p1(x,y)
,那么类别为2
即 选择高概率对应的类别
贝叶斯概率以18世纪的一位神学家托马斯·贝叶斯(Thomas Bayes)的名字命名。
贝叶斯概率引入 先验知识 和 逻辑推理 来处理不确定命题。
另一种概率解释称为频数概率(frequency probability),它只从数据本身获得结论,并不考虑逻辑推理及先验知识。
条件概率

B桶取到灰色石头的概率,这个概率可以记作P(gray|bucketB)
,我们称之为“在已知石头出自B桶的条件下,取出灰色石头的概率”
P(gray|bucketA)
值为2/4,P(gray|bucketB)
的值为1/3
条件概率计算公式:
\[ P(gray|bucketB) = P(gray \ and \ bucketB)/P(bucketB)\]
另一种有效计算条件概率的方法称为贝叶斯准则。
贝叶斯准则告诉我们如何交换条件概率中的条件与结果,
即如果已知
P(x|c)
,要求P(c|x)
,那么可以使用下面的计算方法:![]()
下面讨论 如何结合贝叶斯决策理论使用条件概率?
使用条件概率来分类
- 如果
p1(x, y) > p2(x, y)
,那么属于类别1; - 如果
p2(x, y) > p1(x, y)
,那么属于类别2。
但这两个准则并不是贝叶斯决策理论的所有内容。
使用p1( )
和p2( )
只是为了尽可能简化描述,而真正需要计算和比较的是p(c₁|x, y)
和p(c₂|x, y)
。
这些符号所代表的具体意义是:
给定某个由x、y表示的数据点,那么该数据点来自类别c₁
的概率是多少?数据点来自类别c₂
的概率又是多少?
注意这些概率与刚才给出的概率p(x, y|c₁)
并不一样,不过可以使用贝叶斯准则来交换概率中条件与结果。
具体地,应用贝叶斯准则得到:

使用这些定义,可以定义贝叶斯分类准则为:
- 如果
P(c₁|x, y) > P(c₂|x, y)
,那么属于类别c₁
。 - 如果
P(c₁|x, y) < P(c₂|x, y)
,那么属于类别c₂
。
使用贝叶斯准则,可以通过已知的三个概率值来计算未知的概率值。
使用朴素贝叶斯进行文档分类
我们可以观察文档中出现的词,并把每个词的出现或者不出现作为一个特征,这样得到的特征数目就会跟词汇表中的词目一样多。
朴素贝叶斯是上节介绍的贝叶斯分类器的一个扩展,是用于文档分类的常用算法。
朴素贝叶斯的一般过程:
收集数据:可以使用任何方法。本章使用RSS源。
准备数据:需要数值型或者布尔型数据
分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。
训练算法:计算不同的独立特征的条件概率。
测试算法:计算错误率。
使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。
假设词汇表中有1000个单词。
要得到好的概率分布,就需要足够的数据样本,假定样本数为N。
前面讲到的约会网站示例中有1000个实例,手写识别示例中每个数字有200个样本,而决策树示例中有24个样本。
其中,24个样本有点少,200个样本好一些,而1000个样本就非常好了。
约会网站例子中有三个特征。
由统计学知,如果每个特征需要N个样本,那么对于10个特征将需要N10个样本,对于包含1000个特征的词汇表将需要N1000个样本。
可以看到,所需要的样本数会随着特征数目增大而迅速增长。
如果特征之间相互独立,那么样本数就可以从N1000减少到1000×N。
所谓独立(independence)指的是统计意义上的独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。
举个例子讲,假设单词bacon出现在unhealthy后面与出现在delicious后面的概率相同。
当然,我们知道这种假设并不正确,bacon常常出现在delicious附近,而很少出现在unhealthy附近,这个假设正是朴素贝叶斯分类器中朴素(naive)一词的含义。朴素贝叶斯分类器中的另一个假设是,每个特征同等重要2。其实这个假设也有问题。
如果要判断留言板的留言是否得当,那么可能不需要看完所有的1000个单词,而只需要看10~20个特征就足以做出判断了。
尽管上述假设存在一些小的瑕疵,但朴素贝叶斯的实际效果却很好。
使用Python进行文本分类
这里的特征是来自文本的词条(token),一个词条是字符的任意组合
将每一个文本片段表示为一个词条向量,其中值为1表示词条出现在文档中,0表示词条未出现
接下来首先给出将文本转换为数字向量的过程,然后介绍如何基于这些向量来计算条件概率,并在此基础上构建分类器,
最后还要介绍一些利用Python实现朴素贝叶斯过程中需要考虑的问题。
准备数据:从文本中构建词向量
词表到向量的转换函数
1 |
|
训练算法:从词向量计算概率
前面介绍了如何将一组单词转换为一组数字,接下来看看如何使用这些数字计算概率。
现在已经知道一个词是否出现在一篇文档中,也知道该文档所属的类别。
我们重写贝叶斯准则,将之前的 x、y 替换为w。粗体w表示这是一个向量,即它由多个数值组成。
在这个例子中,数值个数与词汇表中的词个数相同。

我们将使用上述公式,对每个类计算该值,然后比较这两个概率值的大小。
如何计算呢?首先可以通过类别i
(侮辱性留言或非侮辱性留言)中文档数除以总的文档数来计算概率 \(p(c_i)\)。
接下来计算 \(p(w|c_i)\) ,这里就要用到朴素贝叶斯假设。
如果将w展开为一个个独立特征,那么就可以将上述概率写作 \(p(w_0,w_1,w_2 ... w_N|c_i)\) 。
这里假设 所有词都互相独立,该假设也称作 条件独立性假设,它意味着可以使用 \[ p(w_0|c_i) p(w_1|c_i) p(w_2|c_i) ... p(w_N|c_i) \] 来计算上述概率,这就极大地简化了计算的过程。
该函数的伪代码如下:
1 |
|
1 |
|
测试算法:根据现实情况修改分类器
利用贝叶斯分类器对文档进行分类时,要计算多个概率的乘积以获得文档属于某个类别的概率,
即计算 \(p(w_0|1) p(w_1|1) p(w_2|1)\)
如果其中一个概率值为0,那么最后的乘积也为0。
为降低这种影响,可以将所有词的出现数初始化为1,并将分母初始化为2。
1 |
|
1 |
|
另一个遇到的问题是下溢出,这是由于太多很小的数相乘造成的。
当计算乘积
p(w0|ci)p(w1|ci)p(w2|ci)...p(wN|ci)
时,由于大部分因子都非常小,所以程序会下溢出或者得到不正确的答案。(读者可以用Python尝试相乘许多很小的数,最后四舍五入后会得到0。)一种解决办法是对乘积取自然对数。在代数中有
ln(a*b) = ln(a)+ln(b)
,于是通过求对数可以避免下溢出或者浮点数舍入导致的错误。同时,采用自然对数进行处理不会有任何损失。
图4-4给出函数
f(x)
与ln(f(x))
的曲线。检查这两条曲线,就会发现它们在相同区域内同时增加或者减少,并且在相同点上取到极值。
它们的取值虽然不同,但不影响最终结果。通过修改
return
前的两行代码,将上述做法用到分类器中:
1 |
|

图4-4 函数
f(x)
与ln(f(x))
会一块增大。这表明想求函数的最大值时,可以使用该函数的自然对数来替换原函数进行求解
1 |
|
准备数据:文档词袋模型
词集模型(set-of-words model):将每个词的出现与否作为一个特征
词袋模型(bag-of-words model):如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中所不能表达的某种信息
在词袋中,每个单词可以出现多次,而在词集中,每个词只能出现一次。
为适应词袋模型,需要对函数
setOfWords2Vec()
稍加修改,修改后的函数称为bagOfWords2Vec()
。
1 |
|
示例:使用朴素贝叶斯过滤垃圾邮件
- 收集数据:提供文本文件。
- 准备数据:将文本文件解析成词条向量。
- 分析数据:检查词条确保解析的正确性。
- 训练算法:使用我们之前建立的
trainNB0()
函数。 - 测试算法:使用
classifyNB()
,并且构建一个新的测试函数来计算文档集的错误率。 - 使用算法:构建一个完整的程序对一组文档进行分类,将错分的文档输出到屏幕上。
准备数据:切分文本
1 |
|
测试算法:使用朴素贝叶斯进行交叉验证
随机选择其中10个文件。
选择出的数字所对应的文档被添加到测试集,同时也将其从训练集中剔除。
这种随机选择数据的一部分作为训练集,而剩余部分作为测试集的过程称为留存交叉验证(hold-out cross validation)
假定现在只完成了一次迭代,那么为了更精确地估计分类器的错误率,就应该进行多次迭代后求出平均错误率。
1 |
|
朴素贝叶斯 小结
首先我们需要先对文本进行切分,这被称为分词,由于训练集和测试集都是英文文本,所以在大多数情况我们只需要按空格切割即可,但是还是有部分符号,如逗号,点,问号,这些符号这被包含于正则表达式,然而还有部分字母是大写的,若目的是句子查找,那么这个特点会很有用,然而这里使用词袋模型,因此希望所有词的形式都是统一的,不论它们出现在句子中间、结尾还是开头,分词完成后,还需要转换为词向量,考虑出现在所有文档中的所有单词,再决定将哪些词纳入词汇表,如 I, am, is 等可作为停用词不纳入词汇表,因为它们在两个类别中出现的频率是相同的,对于分类的作用也就微乎其微,接下来训练算法,从词向量计算概率,对每个类别都计算概率,选择最高概率的类别作为结果。
通过特征之间的条件独立性假设,降低对数据量的需求。
独立性假设是指 一个词的出现概率 并不依赖于文档中的其他词。
这个假设很简单,所以称之为 __朴素__贝叶斯
词袋模型在解决文档分类问题上比词集模型 有所提高
优化点:
- 切分词
- 转成词向量 所使用的模型(词袋,词集)
- 移除停用词
Q&A
Q: 模型选择:为什么选择 多项式贝叶斯 ?
A: 模型需要根据数据集中特征的特点来进行选取,垃圾邮件分类重点在于文档中单词出现的频率以及文档的重要性,
数据并不符合正态分布的特征,并且垃圾邮件判定过程是一个随机事件,单词在邮件中出现的次数并不是固定的,
因此不能选择高斯型分布模型,此处选择多项式分布模型。
多项式朴素贝叶斯分类器适用于具有离散特征的分类
补充

词向量特征构建
具体到文本分类问题中,经典的特征表示方法有词袋模型(Bag of words)和 tf-idf。
1. 词袋模型(Bag of words)
词袋模型故名思议,忽略其词序和语法,句法,将其仅仅看做是一个词集合,使用词袋模型将文本做特征表征就是一个根据词频(term frequency)表示成ones-hot的过程。
sklearn中有CountVectorizer即是它的实现
1 |
|
2. tf-idf
根据词语出现次数 构建词袋 会出现一问题,长文章词语出现次数比短文章词语出现次数多,而实际上两篇文章可能同一主题。
于是,我们用 tf(term frequencies)---单词出现次数除以文章总单词书数,这样的方法来代替出现次数构建词袋字典。
除此之外,还有一问题:若一个词在许多文章中均有出现,那么它对于区分文章类别的作用就微乎其微了。
于是,有了 tf-idf(Term Frequency times Inverse Document Frequency) ---- 每个词再加上权重来构建词标记。
tf-idf算法 在 sklearn 中就是 TfidfTransformer
1 |
|
分类准确率分数 accuracy_score
分类准确率分数 是指所有分类正确的百分比。
分类准确率这一衡量分类器的标准比较容易理解,但是它不能告诉你响应值的潜在分布,并且它也不能告诉你分类器犯错的类型。
召回率 recall_score
召回率 = 提取出的正确信息条数 / 样本中的信息条数。
通俗地说,就是所有准确的条目有多少被检索出来了。
1 |
|
朴素贝叶斯的两种假设
由统计学知,若每个特征需要N个样本,那么对于10个特征将需要N的10次方个样本,对于包含1000个特征的词汇表将需要N的1000次 方个样本。可以看到,所需样本数会随着特征数目增大而迅速增长。
若特征之间相互独立,那么样本数就可以从N的1000次方减少到1000*N。所谓独立,即一个特征或者单词出现的可能性与它和其他单词相邻没有关系。这是朴素贝叶斯的一个假设,它的另一个假设是每个特征(单词)同等重要。
朴素贝叶斯分类器有两种实现方式:
- 基于伯努利模型实现
- 基于多项式模型实现 (伯努利模型方式并不考虑词在文档中出现的次数,只考虑出不出现,因此在这个意义上相当于假设词是等权重的)
多项式朴素贝叶斯
算法评价
参考
感谢帮助!
- Python数据分析:分类分析(classification analysis)
- 安然电子邮件数据集垃圾邮件分类
- 机器学习:朴素贝叶斯邮件分类(python实现)
- 【python文本分类】20行代码识别垃圾邮件
- (计算机应用技术专业论文)基于贝叶斯算法的垃圾邮件过滤研究
- 机器学习之60行代码写个垃圾邮件过滤器
- Ultimate Guide to Understand and Implement Natural Language Processing (with codes in Python)
- 机器学习笔记17 —— 垃圾邮件分类器、查准率和召回率
- sklearn 1.9. 朴素贝叶斯
- scikit-learn机器学习(二)逻辑回归进行二分类 垃圾邮件分类,二分类性能指标,画ROC曲线,计算acc,recall,presicion,f1
- sklearn常见分类器(二分类模板)
- 朴素贝叶斯分类算法 & sklearn中的朴素贝叶斯模型及其应用 & 朴素贝叶斯应用:垃圾邮件分类
- 文本分类:垃圾邮件分类
- 利用sklearn做自然语言处理(NLP)——词向量特征构建
- 深度学习第42讲:自然语言处理之词嵌入和词向量
- 机器学习之sklearn基本分类方法
- 13-垃圾邮件分类2 - 卡哇伊黑猫 - 博客园
- sklearn.metrics中的评估方法介绍(accuracy_score, recall_score, roc_curve, roc_auc_score, confusion_matrix)
- 基于贝叶斯方法的邮件分类技术研究
- NLP | 文本特征向量化方法
- NLP | 文本特征向量化方法 - 知乎专栏
- 朴素贝叶斯算法与垃圾邮件分类
- 使用朴素贝叶斯算法简单实现垃圾邮件过滤之算法介绍
- 朴素贝叶斯算法——实现垃圾邮件过滤(Python3实现)
- 《机器学习实战》[美] Peter Harrington