多元Bernoulli模型的朴素贝叶斯分类器适用于离散数据
。与MultinomialNB不同之处为:
- MultinomialNB使用出现次数(
频数
) - BernoulliNB设计用于
二进制/布尔特征
。
1. 预备知识
- 伯努利试验:设试验E只有两种可能的结果:A和~A,则称E为
伯努利(Bernoulli)试验
。设P(A) = p (0 < p < 1),此时P(~A) = 1 - p 。将E独立重复地进行n次,则称这一串重复的独立试验为n重伯努利实验。 二项分布
(Binomial Distribution),即重复n次的伯努利试验(Bernoulli Experiment),用ξ表示随机试验的结果。如果事件发生的概率是P,则不发生的概率q=1-p,N次独立重复试验中发生K次的概率是
组合
的定义:从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。计算公式:
- 事件的
独立性
:设A,B是两事件,如果满足等式 P(AB) = P(A)P(B),则称事件A,B相互独立,简称A,B独立。
例子:试验E为抛甲、乙两枚硬币,观察正反面出现的情况。设事件A为“甲币出现H”,事件B为“乙币出现H”。E的样本空间为S = {HH , HT , TH , TT}
由数据我们可以得出:
P(A) = 2/4 = 1/2 , P(B) = 2/4 = 1/2
P(B | A) = 1/2 , P(AB) = 1/4
在这里我们看到 P(B | A)= P(B),而 P(AB) = P(A) P(B),从我们的经验出发,显然甲币是否出现正面与乙币是否出现正面是互不影响的!
2. sklearn模块:伯努利模型
class sklearn.naive_bayes.BernoulliNB(alpha=1.0, binarize=0.0, fit_prior=True, class_prior=None)
参数 | alpha : float,optional(default = 1.0) |
---|---|
添加拉普拉修/Lidstone平滑参数(0表示无平滑) | |
fit_prior : boolean,optional(default = True) | |
表示是否学习先验概率,参数为False表示所有类标记具有相同的先验概率 | |
class_prior : array-like,size(n_classes,),可选(默认=None) | |
类别的先验概率。如果指定,则不根据数据调整先验。 | |
binarize : float or None, optional (default=0.0) | |
样本特征的二值化(映射到布尔值)的阈值。如果为None,则假定输入已包含二进制向量。 | |
属性 | class_log_prior_ : array, shape (n_classes, ) |
各类标记的平滑先验概率对数值,其取值会受fit_prior和class_prior参数的影响 | |
feature_log_prob_ : array, shape (n_classes, n_features) | |
给出一个类的特征条件概率P(xi | y)的对数值,返回形状为(n_classes, n_features)数组 | |
class_count_ : array, shape (n_classes,) | |
训练样本中各类别对应的样本数,按类的顺序排序输出 | |
feature_count_ : array, shape (n_classes, n_features) | |
各类别各个特征出现的次数,返回形状为(n_classes, n_features)数组 |
方法如下:
fit(self, X, y, sample_weight=None) | 根据X、y训练模型 |
get_params(deep=True) | 获取分类器的参数,以各参数字典形式返回 |
partial_fit(X, y, classes=None, sample_weight=None) | 对于数据量大时,提供增量式训练,在线学习模型参数,参数X可以是类似数组或稀疏矩阵,在第一次调用函数,必须制定classes参数,随后调用时可以忽略 |
predict(self, X) | 在测试集X上预测,输出X对应目标值 |
predict_log_proba(self, X) | 测试样本划分到各个类的概率对数值 |
predict_proba(self, X) | 输出测试样本划分到各个类别的概率值 |
score(self, X, y[, sample_weight]) | 输出对测试样本的预测准确率的平均值 |
set_params(self, **params) | 设置估计器的参数 |
使用参数、属性和方法与多项式模型雷同,详细可查看sklearn模块之朴素贝叶斯:多项式模型的实现
3. 使用朴素贝叶斯进行文档分类
前提假设:
- 特征之间相互独立
- 每个特征同等重要
朴素贝叶斯适用于文档分类的常用算法。
3.1 词向量、文档词集模型、文档词袋模型
- 词向量:将文档看成单词向量,即将句子转换为向量。因文本都具有不同长度,先统计出一个含所有单词的集合 (
词典
),根据这个集合转换成数字表达的向量。 - 词集模型:将每个词的
出现与否
作为一个特征,该单词出现置为1,否则置为0。 - 词袋模型:如果一个词在文档中出现不止一次,这可能意味着包含该词是否出现在文档中更多的某种信息。(考虑
频数
)
3.2 准备数据:从文本中构建词向量(词集模型)
以在线社区的留言板为例。为了不影响社区的发展,我们要屏蔽侮辱性的言论,所以要构建一个快速过滤器。对问题建立两个类别:侮辱类
和非侮辱类
,使用1和0分别表示。
from sklearn.naive_bayes import BernoulliNB
import numpy as np
# 构建数据集
def createDateSet():
postingList = [['my','dog','has','flea','problems','help','please'],
['maybe','not','take','him','to','dog','park','stupid'],
['my','dalmation','is','so','cute','I','love','him'],
['stop','posting','stupid','worthless','garbage'],
['mr','licks','ate','my','steak','how','to','stop','him'],
['quit','buying','worthing','dog','food','stupid']]
classVec = [0,1,0,1,0,1]
return postingList,classVec
# 生成词典
def createWordDict(dataSet):
vocabSet = set([])
for wordList in dataSet:
vocabSet = vocabSet | set(wordList)
return list(vocabSet)
# 将每行数据向量化
def setOfWordsVec(wordList,document):
returnVec = [0] * len(document)
for word in wordList:
if word in document:
returnVec[document.index(word)] = 1
return returnVec
if __name__ == '__main__':
postingList,classLabels = createDateSet()
document = createWordDict(postingList)
## 词向量矩阵
wordsVecSet = []
for wordList in postingList:
wordsVecSet.append(setOfWordsVec(wordList,document))
# 已将数据集转换为词向量矩阵
print(wordsVecSet)
输出:
[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0],
[1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1],
[0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0]]
3.4 使用sklearn模块实现伯努利模型进行分类
# 使用伯努利模型
clf = BernoulliNB()
clf.fit(wordsVecSet,classLabels)
new_words = ['stupid','garbage']
new_words_vec = setOfWordsVec(new_words,document)
# 预测
print(clf.predict([new_words_vec]))
# 评估精度 正确的标签为[ 0,1 ]
print(clf.score([[0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0]],
[1,0]))
输出:
[1]
参考资料:《机器学习实战》