文章原创,最近更新:2018-08-21
学习参考链接:第4章 基于概率论的分类方法:朴素贝叶斯
本章节的主要内容是:
重点介绍项目案例1:屏蔽社区留言板的侮辱性言论:朴素贝叶斯分类函数 的代码
。
1.朴素贝叶斯项目案例介绍:
项目案例1:
屏蔽社区留言板的侮辱性言论
项目概述:
构建一个快速过滤器来屏蔽在线社区留言板上的侮辱性言论。如果某条留言使用了负面或者侮辱性的语言,那么就将该留言标识为内容不当。对此问题建立两个类别: 侮辱类和非侮辱类,使用 1 和 0 分别表示。
朴素贝叶斯 工作原理:
提取所有文档中的词条并进行去重
获取文档的所有类别
计算每个类别中的文档数目
对每篇训练文档:
对每个类别:
如果词条出现在文档中-->增加该词条的计数值(for循环或者矩阵相加)
增加所有词条的计数值(此类别下词条总数)
对每个类别:
对每个词条:
将该词条的数目除以总词条数目得到的条件概率(P(词条|类别))
返回该文档属于每个类别的条件概率(P(类别|文档的所有词条))
开发流程:
- 收集数据: 可以使用任何方法
- 准备数据: 从文本中构建词向量
- 分析数据: 检查词条确保解析的正确性
- 训练算法: 从词向量计算概率
- 测试算法: 根据现实情况修改分类器
- 使用算法: 对社区留言板言论进行分类
数据集介绍
这个数据集是我们自己构造的词表.
2.朴素贝叶斯分类函数
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1):
"""
使用算法:
# 将乘法转换为加法
乘法:P(C|F1F2...Fn) = P(F1F2...Fn|C)P(C)/P(F1F2...Fn)
加法:P(F1|C)*P(F2|C)....P(Fn|C)P(C) -> log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C))
:param vec2Classify: 待测数据[0,1,1,1,1...],即要分类的向量
:param p0Vec: 类别0,即正常文档的[log(P(F1|C0)),log(P(F2|C0)),log(P(F3|C0)),log(P(F4|C0)),log(P(F5|C0))....]列表
:param p1Vec: 类别1,即侮辱性文档的[log(P(F1|C1)),log(P(F2|C1)),log(P(F3|C1)),log(P(F4|C1)),log(P(F5|C1))....]列表
:param pClass1: 类别1,侮辱性文件的出现概率
:return: 类别1 or 0
"""
# 计算公式 log(P(F1|C))+log(P(F2|C))+....+log(P(Fn|C))+log(P(C))
# 大家可能会发现,上面的计算公式,没有除以贝叶斯准则的公式的分母,也就是 P(w) (P(w) 指的是此文档在所有的文档中出现的概率)就进行概率大小的比较了,
# 因为 P(w) 针对的是包含侮辱和非侮辱的全部文档,所以 P(w) 是相同的。
# 使用 NumPy 数组来计算两个向量相乘的结果,这里的相乘是指对应元素相乘,即先将两个向量中的第一个元素相乘,然后将第2个元素相乘,以此类推。
# 我的理解是:这里的 vec2Classify * p1Vec 的意思就是将每个词与其对应的概率相关联起来
# P(w|c1) * P(c1) ,即贝叶斯准则的分子
p1=sum(vec2Classify*p1Vec)+np.log(pClass1)
# P(w|c0) * P(c0) ,即贝叶斯准则的分子·
p0=sum(vec2Classify*p0Vec)+np.log(1.0-pClass1)
if p1>p0:
return 1
else:
return 0
def testingNB():
"""
测试朴素贝叶斯算法
"""
listOPosts,listClasses = loadDataSet()
# 创建包含在所有文档中不出现重复词对列表,即创建特征
myVocabList = createVocabList(listOPosts)
# 获取文档向量,向量的每一个元素为1或者0,分别表示词表中的单词在输入文档中是否出现
trainMat=[]
for postinDoc in listOPosts:
# 训练贝叶斯分类器
trainMat.append(setOfWords2Vec(myVocabList, postinDoc))
p0V,P1V,PAb =trainNB0(trainMat, listClasses)
# 测试一
#创建测试样本
testEntry = ['love', 'my', 'dalmation']
#获取测试样本特征向量
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
#输出分类结果
print (testEntry,'分类结果: ',classifyNB(thisDoc,p0V,P1V,PAb))
# 测试二
#创建测试样本
testEntry = ['stupid', 'garbage']
#获取测试样本特征向量
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
#输出分类结果
print (testEntry,'分类结果: ',classifyNB(thisDoc,p0V,P1V,PAb))
测试代码及其结果如下:
import bayes
bayes.testingNB()
['love', 'my', 'dalmation'] 分类结果: 0
['stupid', 'garbage'] 分类结果: 1
小结:
-
为突出重点,本文示例仅采用两个分类做测试。更多分类是同理的。
-
程序设计中应尽量以矩阵或者向量为单位来处理数据。这样能简化代码,增加效率,也能提高程序可读性。
-
该分类算法的优点是对于数据集较少的情况也能适用,能处理多类别问题;然而不足之处在于对数据集的准备方式比较敏感。
网友评论