机器学习笔记:朴素贝叶斯方法(Naive Bayes)原理和实现
2015-04-13 00:25
375 查看
本文主要描述了朴素贝叶斯分类方法,包括模型导出和学习描述。实例部分总结了《machine learning in action》一书中展示的一个该方法用于句子感情色彩分类的程序。1
方法概述
学习(参数估计)
实现:朴素贝叶斯下的文本分类
朴素:特征条件独立
贝叶斯:基于贝叶斯定理
根据贝叶斯定理,对一个分类问题,给定样本特征x,样本属于类别y的概率是
p(y|x)=p(x|y)p(y)p(x)。。。。。。(1) p(y|x) = \dfrac{p(x|y)p(y)}{p(x)} 。。。。。。(1)
在这里,x是一个特征向量,将设x维度为M。因为朴素的假设,即特征条件独立,根据全概率公式展开,公式(1)可以表达为
p(y=ck|x)=∏Mi=1p(xi|y=ck)p(y=ck)∑kp(y=ck)∏Mi=1P(xi|y=ck)。。。。(2)p(y=c_k|x)=\dfrac{\prod_{i=1}^{M}p(x^i|y=c_k)p(y=c_k)}{\sum_kp(y=c_k)\prod_{i=1}^{M}P(x^i|y=c_k)}。。。。(2)
这里,只要分别估计出,特征xix^i在每一类的条件概率就可以了。类别y的先验概率可以通过训练集算出,同样通过训练集上的统计,可以得出对应每一类上的,条件独立的特征对应的条件概率向量。
如何统计,就是下一部分——学习——所关心的内容。
学习 1.首先,我们来计算公式(2)中的p(y=ck)p(y=c_k)
p(y=ck)=∑Ni=1I(yi=ck)N。。。。(3)p(y=c_k)=\dfrac{\sum_{i=1}^{N}I(y_i=c_k)}{N}。。。。(3)
其中I(x)I(x)为指示函数,若括号内成立,则计1,否则为0。
学习 2.接下来计算分子中的条件概率,设MM维特征的第jj维有LL个取值,则某维特征的某个取值ajla_{jl},在给定某分类ckc_k下的条件概率为:
p(xj=ajl|y=ck)=∑Ni=1I(xji=ajl,yi=ck)∑Ni=1I(yi=ck)。。。(4)p(x^j=a_{jl}|y=c_k)=\dfrac{\sum_{i=1}^{N}I(x_i^{j}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)}。。。(4)
经过上述步骤,我们就得到了模型的基本概率,也就完成了学习的任务。
分类 1.计算该实例属于y=cky=c_k类的概率
p(y=ck|X)=p(y=ck)∏j=1np(X(j)=x(j)|y=ck)。。。(5)p(y=c_k|X)=p(y=c_k)\prod_{j=1}^{n}p(X^{(j)}=x^{(j)}|y=c_k)。。。(5)
分类 2.确定该实例所属的分类yy
y=argmaxckp(y=ck|X)。。。。(6)y=arg\max_{ c_k}p(y=c_k|X)。。。。(6)
于是我们得到了新实例的分类结果
下面介绍一种简单方法,给学习步骤中的两个概率计算公式,分子和分母都分别加上一个常数,就可以避免这个问题。更新过后的公式如下:
p(y=ck)=∑Ni=1I(yi=ck)+λN+Kλ。。。。(7)p(y=c_k)=\dfrac{\sum_{i=1}^{N}I(y_i=c_k)+ \lambda}{N+K\lambda}。。。。(7)
KK是类的个数
p(xj=ajl|y=ck)=∑Ni=1I(xji=ajl,yi=ck)+λ∑Ni=1I(yi=ck)+Ljλ。。。(8)p(x^j=a_{jl}|y=c_k)=\dfrac{\sum_{i=1}^{N}I(x_i^{j}=a_{jl},y_i=c_k)+ \lambda}{\sum_{i=1}^{N}I(y_i=c_k)+L_j\lambda}。。。(8)
LjL_j是第jj维特征的最大取值
可以证明,改进以后的(7)(8)仍然是概率。平滑因子λ=0\lambda=0即为(3)(4)实现的最大似然估计,这时会出现在本节开始时提到的0概率问题;而λ=1\lambda=1则避免了0概率问题,这种方法被称为拉普拉斯平滑。
下面简述实现思想和流程,给出代码。
由以上的基础,应用朴素贝叶斯分类,就变成了这样的问题
初始化步,构建可以表征句子的特征向量(词汇表)。并根据这个特征向量,把训练集表征出来。从训练集中分离部分数据作为测试集。
学习步,计算类的先验概率和特征向量对应每一类的条件概率向量
分类步, 计算测试集中待分类句子在每一类的分类后验概率,取最大值作为其分类,并与给定标签比较,得到误分类率。
训练:
分类:
注意:上述代码中标有注意的地方,是公式中概率连乘变成了对数概率相加。此举可以在数学上证明不会影响分类结果,且在实际计算中,避免了因概率因子远小于1而连乘造成的下溢出。
模型概述
学习参数估计
学习
分类
拉普拉斯平滑
实现朴素贝叶斯下的文本分类
算法思想和流程
代码
参考:
李航. (2012). 统计学习方法.
Harrington, P. (2013). 机器学习实战. 人民邮电出版社, 北京 ↩
方法概述
学习(参数估计)
实现:朴素贝叶斯下的文本分类
模型概述
朴素贝叶斯方法,是指朴素:特征条件独立
贝叶斯:基于贝叶斯定理
根据贝叶斯定理,对一个分类问题,给定样本特征x,样本属于类别y的概率是
p(y|x)=p(x|y)p(y)p(x)。。。。。。(1) p(y|x) = \dfrac{p(x|y)p(y)}{p(x)} 。。。。。。(1)
在这里,x是一个特征向量,将设x维度为M。因为朴素的假设,即特征条件独立,根据全概率公式展开,公式(1)可以表达为
p(y=ck|x)=∏Mi=1p(xi|y=ck)p(y=ck)∑kp(y=ck)∏Mi=1P(xi|y=ck)。。。。(2)p(y=c_k|x)=\dfrac{\prod_{i=1}^{M}p(x^i|y=c_k)p(y=c_k)}{\sum_kp(y=c_k)\prod_{i=1}^{M}P(x^i|y=c_k)}。。。。(2)
这里,只要分别估计出,特征xix^i在每一类的条件概率就可以了。类别y的先验概率可以通过训练集算出,同样通过训练集上的统计,可以得出对应每一类上的,条件独立的特征对应的条件概率向量。
如何统计,就是下一部分——学习——所关心的内容。
学习(参数估计)
下面介绍如何从数据中,学习得到朴素贝叶斯分类模型。概述分类方法,并提出一个值得注意的问题。学习
训练集TrainingSet={(x1,y1),(x2,y2),...,(xN,yN)}\{(x_1,y_1),(x_2,y_2),...,(x_N,y_N)\} 包含N条训练数据,其中 xi=(x(1)i,x(2)i,...,x(M)i)Tx_i=(x_{i}^{(1)},x_{i}^{(2)},...,x_{i}^{(M)})^T是M维向量,yi∈{c1,c2,...cK}y_i\in\{c_1,c_2,...c_K\}属于K类中的一类。学习 1.首先,我们来计算公式(2)中的p(y=ck)p(y=c_k)
p(y=ck)=∑Ni=1I(yi=ck)N。。。。(3)p(y=c_k)=\dfrac{\sum_{i=1}^{N}I(y_i=c_k)}{N}。。。。(3)
其中I(x)I(x)为指示函数,若括号内成立,则计1,否则为0。
学习 2.接下来计算分子中的条件概率,设MM维特征的第jj维有LL个取值,则某维特征的某个取值ajla_{jl},在给定某分类ckc_k下的条件概率为:
p(xj=ajl|y=ck)=∑Ni=1I(xji=ajl,yi=ck)∑Ni=1I(yi=ck)。。。(4)p(x^j=a_{jl}|y=c_k)=\dfrac{\sum_{i=1}^{N}I(x_i^{j}=a_{jl},y_i=c_k)}{\sum_{i=1}^{N}I(y_i=c_k)}。。。(4)
经过上述步骤,我们就得到了模型的基本概率,也就完成了学习的任务。
分类
通过学到的概率,给定未分类新实例XX,就可以通过上述概率进行计算,得到该实例属于各类的后验概率p(y=ck|X)p(y=c_k|X),因为对所有的类来说,公式(2)中分母的值都相同,所以只计算分子部分即可,具体步骤如下:分类 1.计算该实例属于y=cky=c_k类的概率
p(y=ck|X)=p(y=ck)∏j=1np(X(j)=x(j)|y=ck)。。。(5)p(y=c_k|X)=p(y=c_k)\prod_{j=1}^{n}p(X^{(j)}=x^{(j)}|y=c_k)。。。(5)
分类 2.确定该实例所属的分类yy
y=argmaxckp(y=ck|X)。。。。(6)y=arg\max_{ c_k}p(y=c_k|X)。。。。(6)
于是我们得到了新实例的分类结果
拉普拉斯平滑
到这里好像方法已经介绍完了,实则有一个小问题需要注意,在公式(3)(4)中,如果从样本中算出的概率值为0该怎么办呢?下面介绍一种简单方法,给学习步骤中的两个概率计算公式,分子和分母都分别加上一个常数,就可以避免这个问题。更新过后的公式如下:
p(y=ck)=∑Ni=1I(yi=ck)+λN+Kλ。。。。(7)p(y=c_k)=\dfrac{\sum_{i=1}^{N}I(y_i=c_k)+ \lambda}{N+K\lambda}。。。。(7)
KK是类的个数
p(xj=ajl|y=ck)=∑Ni=1I(xji=ajl,yi=ck)+λ∑Ni=1I(yi=ck)+Ljλ。。。(8)p(x^j=a_{jl}|y=c_k)=\dfrac{\sum_{i=1}^{N}I(x_i^{j}=a_{jl},y_i=c_k)+ \lambda}{\sum_{i=1}^{N}I(y_i=c_k)+L_j\lambda}。。。(8)
LjL_j是第jj维特征的最大取值
可以证明,改进以后的(7)(8)仍然是概率。平滑因子λ=0\lambda=0即为(3)(4)实现的最大似然估计,这时会出现在本节开始时提到的0概率问题;而λ=1\lambda=1则避免了0概率问题,这种方法被称为拉普拉斯平滑。
实现:朴素贝叶斯下的文本分类
根据上面的算法流程,在这里实现一个句子极性划分的例子。所谓句子极性是指,句子所表达的情感色彩,例如积极/消极,这里(书里)使用的是侮辱性/非侮辱性。其实是什么类别不重要,只要给定有标签的训练数据,就可以得到分类模型。下面简述实现思想和流程,给出代码。
算法思想和流程
给定的训练集是标定了 侮辱性/非侮辱性 的句子(因为是英语句子,所以基本视分词为已经解决的问题,如果是汉语,则要先进行分词),我们认为特征就是句子中的单个词语。单个词语有极性表征,整个句子所包含的单词的极性表征就是句子的极性。由以上的基础,应用朴素贝叶斯分类,就变成了这样的问题
初始化步,构建可以表征句子的特征向量(词汇表)。并根据这个特征向量,把训练集表征出来。从训练集中分离部分数据作为测试集。
学习步,计算类的先验概率和特征向量对应每一类的条件概率向量
分类步, 计算测试集中待分类句子在每一类的分类后验概率,取最大值作为其分类,并与给定标签比较,得到误分类率。
代码
初始化:def loadDataSet():#数据格式 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', 'worthless', 'dog', 'food', 'stupid']] classVec = [0,1,0,1,0,1]#1 侮辱性文字 , 0 代表正常言论 return postingList,classVec def createVocabList(dataSet):#创建词汇表 vocabSet = set([]) for document in dataSet: vocabSet = vocabSet | set(document) #创建并集 return list(vocabSet) def bagOfWord2VecMN(vocabList,inputSet):#根据词汇表,讲句子转化为向量 returnVec = [0]*len(vocabList) for word in inputSet: if word in vocabList: returnVec[vocabList.index(word)] += 1 return returnVec
训练:
def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[0]) pAbusive = sum(trainCategory)/float(numTrainDocs) p0Num = ones(numWords);p1Num = ones(numWords)#计算频数初始化为1 p0Denom = 2.0;p1Denom = 2.0 #即拉普拉斯平滑 for i in range(numTrainDocs): if trainCategory[i]==1: p1Num += trainMatrix[i] p1Denom += sum(trainMatrix[i]) else: p0Num += trainMatrix[i] p0Denom += sum(trainMatrix[i]) p1Vect = log(p1Num/p1Denom)#注意 p0Vect = log(p0Num/p0Denom)#注意 return p0Vect,p1Vect,pAbusive#返回各类对应特征的条件概率向量 #和各类的先验概率
分类:
def classifyNB(vec2Classify,p0Vec,p1Vec,pClass1): p1 = sum(vec2Classify * p1Vec) + log(pClass1)#注意 p0 = sum(vec2Classify * p0Vec) + log(1-pClass1)#注意 if p1 > p0: return 1 else: return 0 def testingNB():#流程展示 listOPosts,listClasses = loadDataSet()#加载数据 myVocabList = createVocabList(listOPosts)#建立词汇表 trainMat = [] for postinDoc in listOPosts: trainMat.append(setOfWords2Vec(myVocabList,postinDoc)) p0V,p1V,pAb = trainNB0(trainMat,listClasses)#训练 #测试 testEntry = ['love','my','dalmation'] thisDoc = setOfWords2Vec(myVocabList,testEntry) print testEntry,'classified as: ',classifyNB(thisDoc,p0V,p1V,pAb)
注意:上述代码中标有注意的地方,是公式中概率连乘变成了对数概率相加。此举可以在数学上证明不会影响分类结果,且在实际计算中,避免了因概率因子远小于1而连乘造成的下溢出。
模型概述
学习参数估计
学习
分类
拉普拉斯平滑
实现朴素贝叶斯下的文本分类
算法思想和流程
代码
参考:
李航. (2012). 统计学习方法.
Harrington, P. (2013). 机器学习实战. 人民邮电出版社, 北京 ↩
相关文章推荐
- 机器学习笔记:朴素贝叶斯方法(Naive Bayes)原理和实现
- 朴素贝叶斯方法(Naive Bayes)原理和实现
- 机器学习入门学习笔记:(一)BP神经网络原理推导及程序实现
- [机器学习]机器学习笔记整理08- SVM算法原理及实现
- 【机器学习实战之二】:C++实现基于概率论的分类方法--朴素贝叶斯分类(Naive Bayes Classifier)
- 朴素贝叶斯方法(Naive Bayes)原理
- 朴素贝叶斯分类算法原理与Python实现与使用方法案例
- 机器学习第四篇(stanford大学公开课学习笔记) —生成型学习算法之高斯判别分析模型和朴素贝叶斯方法
- [笔记-机器学习]贝叶斯分类器的原理及实现
- scikit-learn机器学习(六)--朴素贝叶斯分类原理及python实现
- 机器学习笔记(一)朴素贝叶斯的Python代码实现
- 机器学习之KNN算法原理及Python实现方法详解
- [SOA]学习《SOA 原理。方法。实践》笔记 (2)
- CRC算法原理及C语言实现(介绍了3种方法)
- Sruts 笔记一(基本实现原理)
- MmMapIoSpace以及MmUnmapIoSpace,VirtualAlloc和VirtualCopy 函数的实现原理以及实现方法
- 命令模式中Undo/Redo的实现原理和方法
- 了解MmMapIoSpace以及MmUnmapIoSpace函数的实现原理以及实现方法
- Struts 2 拦截器底层实现原理 学习笔记
- [SOA]学习《SOA 原理。方法。实践》笔记 (3)