开篇为我们讲解了许多实际应用情况下,我们可能不需要得到精准的分类,而是属于某一类的概率,以及属于其他类的概率。
这里我就简单的以论坛侮辱性言语检测为例,来讲一下算法的流程。
函数伪代码是:
计算每个类别的文档数目
对每篇训练文档:
对每个类别:
如果词条出现在了这个文档中->增加该文档的计数值
增加所有词条的计数值
对每个类别:
对每个词条:
将该词条的数目除以总体条数目得到条件概率
返回每个类别的条件概率
这里对词条,文档的概念进行图解:
首先是文档,这里面我们输入了6个文档构成了trainMat:
就像ABCDEF所示,并且我们加上了先验的labels,1代表侮辱性言论,0代表非侮辱性言论。
那么接下来我们生成了个list,这个list的生成使用了set()函数,这就保证了这个词条(list)所具有的每个单词都是唯一的(unique),那么算法首先将整个词条进行了二值化,也就是通过bayse.setOfWords2Vec()来对词条进行判断,这个判断进行了6次(次数等于文档的个数),如果这个单词出现在了1中,就付给它1的值,那么最后我们得到了一个trainMat,这个trainMat是6×32的训练矩阵,32是由list的长度所决定的。
接下来算法做的事情就是遍历每一个一个文档,然后找出根据文档是攻击性还是非攻击性,统计出某个单词在攻击性或非攻击性语句下出现的次数,用这个次数比上这类语句的总单词数,就是这个单词的p(wi|c1)或者P(wi|c2)。
因为python在处理非常小的数据的时候会在多次乘法之后将近似0的数舍入为0,为了避免这个问题,我们将其转换为log的对数形式,这里我们知道对数函数是单调递增的,那么经过对数变换之后的概率也将会保持其大小关系不变,而ln(a*b)=ln(a)+ln(b)也方便我们通过sum的形式就可以实现概率的乘积。
我们得到的p0v和p1v就是代表这个list中每个单词在非侮辱性文档及侮辱性文档中出现的概率。
我们将这两个概率保存下载,接下来针对一个待测试的文档,我们计算这个文档中的每一个单词对应的p1v和p0v的概率和,这个概率和就是根据p(wi|c1)和p(wi|c0)来计算得到的,得到p1和p0两个概率,如果p1大,那么就认为这段话是侮辱性言论,如果P0大,那么就认为这段话是正常言论,这里就要求我们这个新的待测试文档中的单词需要尽可能的出现在我们的List中。
词袋模型:每个单词可以出现一次以上;
词集模型:每个单词只能至多出现一次。
词袋模型得到的结果将会是list单词个数维度下面的['1','2','4','0','0','1'],而不再是像词集下我们得到的只有0或1表征出现与否的list。
涉及到文本切分问题,我们使用.split()进行文本的切分,同时利用
import re
regEx = re.complie('\\W*')
listOfTokens = regEx.split(mySent)
命令,\\w代表任何非字幕的单词,这里我们要做的就是将除了字母以外的单词都加入到需要作为split标记的部分。
python自己就提供了大小写变换的语句,我们通过word.lower()就可以将整个word中的内容都变成我们需要的小写的形式了。
通过设定len(tok)>2,我们也可以去除掉一些空字符和单独的字母。
对于算法的检测,我们可以建立一种交叉验证的关系,也就是我们在书中所提到的“留存交叉验证”,随机选择数据集合中的一部分作为测试样本,而将除去训练样本之外剩下的一部分作为测试样本。
书中给的程序里面少了这样一句话:
print "classification error",docList[docIndex]
这个用来输出出现分组错误的邮件的内容,方便我们修改自己的算法。
贝叶斯概率及贝叶斯准则提供了一种利用已知来估计未知的有效方法。
朴素的贝叶斯概率假定所有单词之间出现的关系都是独立的,这显然是一种朴素的,不切合实际的估计。尽管如此,朴素贝叶斯分类器仍然是一种有效的分类工具。