Python贝叶斯文本分类模型从原理到实现_第1页
Python贝叶斯文本分类模型从原理到实现_第2页
Python贝叶斯文本分类模型从原理到实现_第3页
Python贝叶斯文本分类模型从原理到实现_第4页
Python贝叶斯文本分类模型从原理到实现_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Python贝叶斯文本分类模型从原理到实现朴素贝叶斯分类器是一种有监督学习,常见有两种模型,多项式模型(multinomial model)即为词频型和伯努利模型(Bernoulli model)即文档型。二者的计算粒度不一样,多项式模型以单词为粒度,伯努利模型以文件为粒度,因此二者的先验概率和类条件概率的计算方法都不同。计算后验概率时,对于一个文档d,多项式模型中,只有在d中出现过的单词,才会参与后验概率计算,伯努利模型中,没有在d中出现,但是在全局单词表中出现的单词,也会参与计算,不过是作为“反方”参与的(避免消除测试文档时类条件概率中有为0现象而做的取对数等问题)。一、数据集数据集是有8

2、个分类的文本数据集,使用了结巴分词对每个文本分词,每个单词当作特征,再利用二元词串构造更多特征,然后去掉停用词,去掉出现次数太多和太少的特征,得到了19630个特征。取1998个样本用于训练,509个用于测试。基于词袋模型的思路将每个文本转换为向量,训练集和测试集分别转换为矩阵,并用python numpy模块将其保存为npy格式。数据集共使用了19630个单词作为特征,特征值是词在文本中出现的次数。8个分类,分别是1、2、.、8。训练集共1998个样本,测试集共509个样本。 二、朴素贝叶斯分类器划分邮件算法朴素贝叶斯分类器,基于贝叶斯定理,是一个表现良好的分类方法。1、公式原理推导 主要根

3、据事件间的相互影响进行公式推断。1.1、条件概率:P(A|B) = P(A,B)/P(B)A和B是随机事件,P(A|B)也就是在事件B发生的前提下事件A发生的概率。 P(A,B)表示A、B都发生的概率。这样一来,我们可以通过统计结果计算条件概率。例如假设有1000封邮件,垃圾邮件有300封,出现单词购买的邮件为50封,而即是垃圾邮件又同时出现了购买这个单词的邮件共有20封。如果把垃圾邮件看成事件A,邮件里出现单词购买看成事件B,那么P(A)是指垃圾邮件出现的概率,因为没考虑其他的因素对A的影响,也可以将P(A)看做A的先验概率,这里:P(A) = 300/1000 = 0.3同理,P(B) =

4、 50/1000 = 0.05P(A,B)是指A和B同时发生的概率,P(A,B) = 20/1000 = 0.02根据条件概率的公式,能够得到P(A|B) = 0.02 / 0.05 = 0.4因为有B的影响,P(A|B)也叫做A的后验概率。1.2、相互独立事件如果事件A和B是相互独立的,代表着A发生的可能性对B发生的可能性没有影响,B也对A没有影响,在这种情况下:P(A,B) = P(A)*P(B)。既然A和B之间没有相互影响,那么:P(A|B) = P(A,B)/P(B) = P(A)P(B|A) = P(A,B)/P(A) = P(B)1.3、贝叶斯定理由P(A|B) = P(A,B)/

5、P(B) 很容易推出:P(A|B) = P(B|A)*P(A)/P(B)这也就是贝叶斯公式了。1.4、朴素贝叶斯分类器(naive Bayes classifier)首先有以下定理:如果B、C相互独立,那么P(B|C,A) = P(B|A)。设有事件A、B1、B2,那么在B1、B2同时发生的前提下,A发生的概率是:P(A|B1,B2) = P(B1,B2|A)*P(A) / P(B1,B2)如果B1和B2相互独立,那么有P(B1,B2|A) = P(B1|B2,A)*P(B2|A)= P(B1|A)*P(B2|A)于是,P(A|B1,B2) = P(B1,B2|A)*P(A) / P(B1,B

6、2) = P(B1|A)*P(B2|A)*P(A) / P(B1,B2)根据实际需求,假设某个体有n项特征(可以看着邮件中出现的词语),分别为F1、F2、Fn。现有m个类别(可以看着邮件的分类),分别为C1、C2、Cm。贝叶斯分类器就是计算出概率最大的那个分类,也就是求下面这个算式的最大值(即算出每个分类的概率,以最大概率为最终分类):P(C|F1,F2,.,Fn)= P(F1,F2,.,Fn|C)*P(C) / P(F1,F2,.,Fn)由于 P(F1,F2,.,Fn)对于所有的类别都是相同的,可以省略,问题就变成了求P(F1,F2,.,Fn|C)*P(C) 的最大值。朴素贝叶斯分类器则是更

7、进一步,假设所有特征都彼此独立,因此P(F1,F2,.,Fn|C)*P(C)= P(F1|C)*P(F2|C)* . *P(Fn|C)*P(C)朴素贝叶斯分类器假设所有特征都彼此独立存在一定的不合理性,不过该分类器一般能取得很好的分类效果。2、判断邮件是否为垃圾邮件假定我们现在有1000封被标识的邮件作为训练集,训练集一般是人工标识,分为“垃圾邮件”、“正常邮件”。注意,训练集不宜人为地从大量邮件中有意挑拣,而应随机挑拣。然后我们从邮件中选取特征,例如我们把单词“购买”是否出现在邮件中看作是该邮件的一个特征,训练时候应该记录含有单词“购买”的垃圾邮件有多少封,含有单词“购买”的正常邮件有多少封

8、,按照这个思路,我们得到以下表格:特征词统计正常邮件垃圾邮件汇总“购买”10 50 60“淘宝”8 5664“开心”60363“编程”201535汇总98124222好了,现在有一封邮件需要分类,假设它有购买、淘宝、开心、编程四个特征,那么其属于正常邮件的可能性是: 10/98 * 8/98 * 60/98 * 20/98 * 98/222 = 0.000459属于垃圾邮件的可能性是:50/124 * 56/124 * 3/124 * 15/124 * 124/222 = 0.00029768结果是该邮件更有可能是正常邮件。如果邮件只有有开心和编程两个特征,那么其属于正常邮件的可能性是:60/

9、98 * 20/98 * 98/222= 0.0551571属于垃圾邮件的可能性是:3/124 * 15/124 * 124/222= 0.0016346992153443768结果是该邮件更有可能是正常邮件。3、让分类器更合理如果我们的统计结果是这样的:特征词统计正常邮件垃圾邮件汇总(求和)“购买”105060“淘宝”85664“开心”63063“编程”201535汇总(求和)101121222具有特征开心的垃圾邮件有0封。如果某封邮件具有购买、淘宝、开心这三个特征,按照上面的思路,该邮件属于正常邮件的可能性是:10/101 * 8/101 * 63/101 * 101/222= 0.002

10、22553属于垃圾邮件的可能性是:50/121 * 56/121 * 0/121 * 121/222= 0这意味着,只要邮件里有“开心”,那么它就不是垃圾邮件(属于垃圾邮件的可能性为0),这显然是不合理的。对此,我们可以对P(F1|C)(以及P(F2|C)、P(F3|C)等)做如下处理(加权平均):P2(F1|C) = (1*0.5 + sum(F1)*P(F1|C) / (1 + sum(F1) = (0.5 + sum(F1)*P(F1|C) / (1 + sum(F1)其中,若F1是开心,那么sum(F1) = 63+0 = 63。于是,属于正常邮件的可能性是:(0.5 + 10/101

11、 * 60) / 61) * (0.5 + 8/101 * 64) / 65) * (0.5 + 63/101 * 63) / 64) * 101/222=0.0025593104680632236属于垃圾邮件的可能性是:(0.5 + 50/121 * 60) / 61) * (0.5 + 56/121 * 64) / 65) * (0.5 + 0/121 * 63) / 64) * 121/222= 0.0008181611103439531这封邮件还是倾向于正常邮件,不过计算方式更合理了。另外我们也可以通过取对数的方式进行优化。这样更合理,因为对数的相乘可以变成相加。4、如何由计算结果判断

12、类别如果计算出一封邮件属于正常邮件的概率是0.05,属于垃圾邮件的概率是0.006,基本可以肯定这是一封正常邮件。不过,如果一封邮件属于正常邮件的概率是0.05,属于垃圾邮件的概率是0.049,那么这封邮件是否该划分为垃圾邮件?也许在这个时候就要在训练之后再填上一个分类了不确定分类。首先,设定一个阈值T(大于1),待标注数据D,两个分类C0和C1,如果:P(C0|D) / P(C1|D) > T那么,D属于类别C0。如果:P(C1|D) / P(C0|D) > T那么,D属于类别C1。5、如果有多个类别对于朴素贝叶斯分类器而言,多个分类和二分类没什么差别,就是训练的时候多加个分类而

13、已。三、贝叶斯模型实现朴素贝叶斯的三个常用模型:高斯、多项式、伯努利朴素贝叶斯的基本若一个样本有n个特征,分别用x1,x2,xn表示,将其划分到类yk的可能性P(yk|x1,x2,xn)为:P(yk|x1,x2,xn)= P(x1|yk)* P(x2|yk)*P(xn|yk)*P(yk)上式中等号右侧的各个值可以通过训练得到。根据上面的公式可以求的某个数据属于各个分类的可能性(这些可能性之和不一定是1),该数据应该属于具有最大可能性的分类中。一般来说,如果一个样本没有特征 xi,那么 P(xi|yk)将不参与计算。不过下面的伯努利模型除外。高斯模型有些特征可能是连续型变量,比如说人的身高,物体

14、的长度,这些特征可以转换成离散型的值,比如如果身高在160cm以下,特征值为1;在160cm和170cm之间,特征值为2;在170cm之上,特征值为3。也可以这样转换,将身高转换为3个特征,分别是f1、f2、f3,如果身高是160cm以下,这三个特征的值分别是1、0、0,若身高在170cm之上,这三个特征的值分别是0、0、1。不过这些方式都不够细腻,高斯模型可以解决这个问题。高斯模型假设这些一个特征的所有属于某个类别的观测值符合高斯分布(正态分布),也就是:下面看一个sklearn中的示例:(需要安装sklearn包)>>> from sklearn import datas

15、ets>>> iris = datasets.load_iris()>>> iris.feature_names # 四个特征的名字'sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'>>> iris.dataarray( 5.1, 3.5, 1.4, 0.2, 4.9, 3. , 1.4, 0.2, 4.7, 3.2, 1.3, 0.2, 4.6, 3.1, 1.5,

16、0.2, 5. , 3.6, 1.4, 0.2, 5.4, 3.9, 1.7, 0.4, 4.6, 3.4, 1.4, 0.3, 5. , 3.4, 1.5, 0.2, . 6.5, 3. , 5.2, 2. , 6.2, 3.4, 5.4, 2.3, 5.9, 3. , 5.1, 1.8) #类型是numpy.array>>> iris.data.size 600 #共600/4=150个样本>>> iris.target_namesarray('setosa', 'versicolor', 'virginica&#

17、39;, dtype='|S10')>>> iris.targetarray(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,., 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, ., 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)>>> iris.target.size150>>> from sklearn.naive_bayes import GaussianNB>>> clf =

18、 GaussianNB()>>> clf.fit(iris.data, iris.target)>>> clf.predict(iris.data0)array(0) # 预测正确>>> clf.predict(iris.data149)array(2) # 预测正确>>> data = numpy.array(6,4,6,2)>>> clf.predict(data)array(2) # 预测结果很合理伯努利模型伯努利模型中,对于一个样本来说,其特征用的是全局的特征。1)基本原理P(c)= 类c下文件总

19、数/整个训练样本的文件总数P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下单词总数+2)2)举例使用前面例子中的数据,模型换成伯努利模型。类yes下总共有3个文件,类no下有1个文件,训练样本文件总数为11,因此P(yes)=3/4, P(Chinese | yes)=(3+1)/(3+2)=4/5,条件概率如下:P(Japan | yes)=P(Tokyo | yes)=(0+1)/(3+2)=1/5P(Beijing | yes)= P(Macao|yes)= P(Shanghai |yes)=(1+1)/(3+2)=2/5P(Chinese|no)=(1+1)/(1+2)=2

20、/3P(Japan|no)=P(Tokyo| no) =(1+1)/(1+2)=2/3P(Beijing| no)= P(Macao| no)= P(Shanghai | no)=(0+1)/(1+2)=1/3有了以上类条件概率,开始计算后验概率,P(yes|d)=P(yes)*P(Chinese|yes)*P(Japan|yes)*P(Tokyo|yes)*(1-P(Beijing|yes)*(1-P(Shanghai|yes)*(1-P(Macao|yes)=3/4*4/5*1/5*1/5*(1-2/5)*(1-2/5)*(1-2/5)=81/156250.005P(no|d)= 1/4*

21、2/3*2/3*2/3*(1-1/3)*(1-1/3)*(1-1/3)=16/7290.022因此,这个文档不属于类别china。在伯努利模型中,每个特征的取值是布尔型的,即true和false,或者1和0。在文本分类中,就是一个特征有没有在一个文档中出现。如果特征值xi值为1,那么P(xi|yk)=P(xi=1|yk)如果特征值xi值为0,那么P(xi|yk)=1P(xi=1|yk)这意味着,“没有某个特征”也是一个特征。下面的示例来自sklearn官方文档:>>> import numpy as np>>> X = np.random.randint(2

22、, size=(6, 100)>>> Y = np.array(1, 2, 3, 4, 4, 5)>>> from sklearn.naive_bayes import BernoulliNB>>> clf = BernoulliNB()>>> clf.fit(X, Y)BernoulliNB(alpha=1.0, binarize=0.0, class_prior=None, fit_prior=True)>>> print(clf.predict(X2)3BernoulliNB()类也有partial

23、_fit()函数。多项式模型该模型常用于文本分类,特征是单词,值是单词的出现次数。1)基本原理在多项式模型中, 设某文档d=(t1,t2,tk),tk是该文档中出现过的单词,允许重复,则先验概率P(c)= 类c下单词总数/整个训练样本的单词总数类条件概率P(tk|c)=(类c下单词tk在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|)V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),|V|则表示训练样本包含多少种单词。 P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)。2)举例给定一组分好类

24、的文本训练数据,如下: 给定一个新样本Chinese Chinese Chinese Tokyo Japan,对其进行分类。该文本用属性向量表示为d=(Chinese, Chinese, Chinese, Tokyo, Japan),类别集合为Y=yes, no。类yes下总共有8个单词,类no下总共有3个单词,训练样本单词总数为11,因此P(yes)=8/11, P(no)=3/11。类条件概率计算如下:P(Chinese | yes)=(5+1)/(8+6)=6/14=3/7P(Japan | yes)=P(Tokyo | yes)= (0+1)/(8+6)=1/14P(Chinese|n

25、o)=(1+1)/(3+6)=2/9P(Japan|no)=P(Tokyo| no) =(1+1)/(3+6)=2/9分母中的8,是指yes类别下textc的长度,也即训练样本的单词总数,6是指训练样本有Chinese,Beijing,Shanghai, Macao, Tokyo, Japan 共6个单词,3是指no类下共有3个单词。有了以上类条件概率,开始计算后验概率:P(yes | d)=(3/7)3×1/14×1/14×8/11=108/1848770.00058417P(no | d)= (2/9)3×2/9×2/9×3/11

26、=32/2165130.00014780比较大小,即可知道这个文档属于类别china。下面的代码来自sklearn的示例:>>> import numpy as np>>> X = np.random.randint(5, size=(6, 100)>>> y = np.array(1, 2, 3, 4, 5, 6)>>> from sklearn.naive_bayes import MultinomialNB>>> clf = MultinomialNB()>>> clf.fit(X

27、, y)MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)>>> print(clf.predict(X2)3值得注意的是,多项式模型在训练一个数据集结束后可以继续训练其他数据集而无需将两个数据集放在一起进行训练。在sklearn中,MultinomialNB()类的partial_fit()方法可以进行这种训练。这种方式特别适合于训练集大到内存无法一次性放入的情况。在第一次调用partial_fit()时需要给出所有的分类标号。>>> import numpy>>> fro

28、m sklearn.naive_bayes import MultinomialNB>>>> clf = MultinomialNB() >>> clf.partial_fit(numpy.array(1,1), numpy.array('aa'), 'aa','bb')GaussianNB()>>> clf.partial_fit(numpy.array(6,1), numpy.array('bb')GaussianNB()>>> clf.predic

29、t(numpy.array(9,1)array('bb', dtype='|S2')在多项式模型中, 设某文档d=(t1,t2,tk),tk是该文档中出现过的单词,允许重复,则先验概率P(c)= 类c下单词总数/整个训练样本的单词总数类条件概率P(tk|c)=(类c下单词tk在各个文档中出现过的次数之和+1)/(类c下单词总数+|V|) V是训练样本的单词表(即抽取单词,单词出现多次,只算一个),|V|则表示训练样本包含多少种单词。 P(tk|c)可以看作是单词tk在证明d属于类c上提供了多大的证据,而P(c)则可以认为是类别c在整体上占多大比例(有多大可能性)

30、。在伯努利模型中:P(c)= 类c下文件总数/整个训练样本的文件总数P(tk|c)=(类c下包含单词tk的文件数+1)/(类c下单词总数+2)导入数据集 import numpy as nptraining_data = np.load("d:/pydata/text-classification/training_data.npy")training_labels = np.load("d:/pydata/text-classification/training_labels.npy")test_data = np.load("d:/pyda

31、ta/text-classification/test_data.npy")test_labels = np.load("d:/pydata/text-classification/test_labels.npy")使用多项式贝叶斯>>> from sklearn.naive_bayes import MultinomialNB>>> clf =MultinomialNB()>>> clf.fit(training_data, training_labels) # 训练模型MultinomialNB(alpha

32、=1.0, class_prior=None, fit_prior=True)>>> predict_labels = clf.predict(test_data) # 预测训练集>>> sum(predict_labels = test_labels) # 预测对了几个?454>>> len(predict_labels) # 训练样本个数509>>> 454./509 # 正确率0.8919449901768173 # 效果不错>>> from sklearn.metrics import confusion_matrix >>> confusion_matrix(test_labels, predict_labels) # 混淆矩阵array( 39, 0, 0, 1, 0, 1, 0, 0, 0, 32, 1, 0, 0, 4, 0, 1, 0, 0, 50, 0, 0, 8, 0, 4, 0, 0, 1, 44, 0, 10, 0, 0, 1, 0, 0, 0, 6

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论