总体把握
关键词:类条件概率密度/似然(likelihood),贝叶斯决策论,极大似然估计,属性条件独立性假设
判别概率/后验概率 =>> 先验概率+类条件概率密度 =>> 概率密度估计(最大似然准则) =>> 属性条件独立
判别式模型:给定x,通过直接建模来预测c,如决策树,神经网络,SVM
生成式模型:给定x,先对联合概率分布建模,然后由此获得,如朴素贝叶斯,隐马尔科夫模型(HMMs)
没有什么事情是举例子解决不了的
我们利用鱼的光泽度指标数据x分为两种鱼. 假定x是连续变量,其分布取决于类别状态,表示成的形式,这就是类条件概率密度函数,即类别状态为时的x的概率密度函数。于是与间的区别就表示了鲈鱼与鲑鱼间光泽度的区别。贝叶斯公式:
是用于归一化的“证据”因子,类先验概率:, 类条件概率密度或者称为似然(likelihood),对给定样本x,证据因子P(x) 与类标记无关,因此估计的问题就转化为如何基于训练数据D来估计先验P(c) 和似然.
- 根据大数定律,当训练集包含充足的独立同分布样本时,P(c) 可通过各类样本出现的频率来进行估计.
- 而直接根据样本出现的频率来估计将会遇到严重的困难,此处引入极大似然估计
左图假定的类条件概率密度函数图,显示了模式处于类别时,观测某个特定特征值x的概率密度。概率函数已经归一化,因此每条曲线下的面积为1.右图是在先验概率,以及上图给出的类条件概率密度的条件下的后验概率。若x=14,那么属于的概率约0.92,属于的概率约为0.08,在每个x处的后验概率之和为1.0。
贝叶斯决策论
贝叶斯判定准则:为了最小化总体风险,只需在每个样本上选择那个能使条件风险最小的类别标记.
假设有N种类别标记,即,是将一个真实标记为的样本误分类为所产生的损失。
基于后验概率可获得样本x分类为所产生的期望损失,即在样本x上的“条件风险”,一次预期的损失被称为一次风险。
我们的任务就是寻找一个判定准则 ,以最小化总体风险
对每个样本x,若判定准则h(x)能最小化条件风险,总体风险也将被最小化。
此时,称为贝叶斯最优分类器。最小化后的总风险值称为贝叶斯风险,反映了分类器所能达到的最好性能。换句话说,基于最小化误差概率
对任给,如果,则判决为
极大似然估计
在典型的监督分类中,估计先验概率没有太大困难,最大的困难在于估计类条件概率密度。估计类条件概率一种常用策略是1.假定其具有某种确定的概率分布形式,2.基于训练样本对概率分布的参数进行估计
例如,假设是一个多元正态分布,均值为,协方差矩阵,这样就把问题从估计完全未知的概率密度转化为估计参数和。假设具有确定的形式并且被参数向量唯一确定,则我们任务是利用训练集D估计参数,我们将记为.
令表示训练集D中第c类的样本合集,假设样本是独立同分布的,则参数对数据集的似然是
对进行极大似然估计就是去寻找能最大化似然的参数值。直观上看,极大似然估计是试图在所有可能取值中,找到一个能使数据出现的“可能性”最大的值。上式的连乘操作会造成下溢,通常使用对数似然(log-likelihood)
此时的最大似然估计为:
例如,在连续属性情形下,假设类条件概率密度函数是正态分布,则参数和的极大似然估计为
没有什么事情是举例子解决不了的
上:一维情况下的训练样本,服从方差已知,均值未知的一维高斯分布
中:似然函数 关于均值的函数图像。如果有非常多的训练样本,波形将更窄
下:对数似然函数
作为一个关于的函数,似然函数,并不表示概率密度,其曲线下的面积也没实际意义。
朴素贝叶斯法
基于贝叶斯公式来估计后验概率的主要困难在于:类条件概率是所有属性上的联合概率,难以从有限的训练样本直接估计而得。为了避开这个障碍,朴素贝叶斯分类器采用“属性条件独立性假设”:对已知类别,假设所有属性相互独立。换言之假设每个属性独立地对分类结果发生影响。根据属性条件独立性假设
其中d为属性数目, 为x在第i个属性上的取值。由于对于所有类别来说相同,因此根据贝叶斯判定准则有
这就是朴素贝叶斯分类器的表达式。其训练过程就是基于训练集D来估计类先验概率,并为每个属性估计条件概率
,表示中在第i个属性上取值为的样本组成的集合,对于连续属性可考虑概率密度函数,假定,其中分别是第c类样本在第i个属性上取值的均值和方差,则有
总结
优点:数据较少情况下仍然有效,
缺点:对输入数据较为敏感
代码
"""判断侮辱恶意词汇"""
import numpy as np
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 is 侮辱性文字, 0 is 正常文字
return postingList,classVec
def creatVocabList(dataset):
"""
创建一个包含在所有文档中出现的不重复词的列表
:param dataset:
:return:
"""
vocabSet = set([])
for document in dataset:
vocabSet = vocabSet | set(document)
return list(vocabSet)
def setWord2vec(vocabList, inputset):
"""
根据vocabList的索引位置,表示单词是否出现,1出现,0未出现
:param vocabList: 词汇表
:param inputset: 输入文本
:return:
"""
returnvec = [0]*len(vocabList)
for word in inputset:
if word in vocabList:
returnvec[vocabList.index(word)] = 1
else:
print("the word: %s is not in my Vocabulary!" % word)
return returnvec
def bagOfWords2VecMN(vocabList, inputSet):
"""
由于一个词在文档中出现次数不止一次,所以此函数每遇见一个单词,就会增加词向量中的对应值,而不是一直设为1
:param vocabList:
:param inputSet:
:return:
"""
returnVec = [0]*len(vocabList)
for word in inputSet:
if word in vocabList:
returnVec[vocabList.index(word)] += 1
return returnVec
def trainNB_0(trainMatrix, trainCategory):
"""
根据训练样本,求出先验类概率密度函数,每个单词为侮辱性词语的概率p1Vect,每个单词不是侮辱词语的概率p0Vect,文档属于侮辱类的概率pAbusive
:param trainMatrix: 文档矩阵
:param trainCategory: 文档矩阵对应的标签向量
:return: p(x|0),p(x|1),p(1)
"""
numTrainLines, numWords = len(trainMatrix),len(trainMatrix[0])
pAbusive = sum(trainCategory)/float(numTrainLines)
# 计算联合概率密度时,乘积元素不能为0,否则结果恒为0,将所有词出现次数初始化为1,分母初始化为2
p0Num,p1Num = np.ones(numWords), np.ones(numWords)
p0Denom = 2.0; p1Denom = 2.0
# 统计训练样本中每个单词在侮辱和非侮辱标签中出现的次数
for i in range(numTrainLines):
if trainCategory[i] == 1:
p1Num += trainMatrix[i]
p1Denom += sum(trainMatrix[i])
else:
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
# 防止下溢
p1Vect = np.log(p1Num/p1Denom) #change to log()
p0Vect = np.log(p0Num/p0Denom) #change to log()
return p0Vect,p1Vect,pAbusive
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
"""
:param vec2Classify: 待分类的词汇索引向量
:param p0Vec: p(x|1)概率密度
:param p1Vec: p(x|0)概率密度
:param pClass1: p(1)
:return:
"""
p1 = sum(vec2Classify * p1Vec) + np.log(pClass1) # element-wise mult
p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
if p1 > p0:
return 1
else:
return 0
if __name__ == "__main__":
listPosts, listLabel = loadDataSet()
myVocabList = creatVocabList(listPosts)
trainMat = []
for postinDoc in listPosts:
trainMat.append(setWord2vec(myVocabList, postinDoc))
p0V, p1V, pAb = trainNB_0(trainMat,listLabel)
testEntry = ['love', 'my', 'dalmation']
thisDoc = np.array(setWord2vec(myVocabList, testEntry))
print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
testEntry = ['stupid', 'garbage']
thisDoc = np.array(setWord2vec(myVocabList, testEntry))
print(testEntry, 'classified as: ', classifyNB(thisDoc, p0V, p1V, pAb))
scikit-learn
-
高斯朴素贝叶斯
GaussianNB
实现了运用于分类的高斯朴素贝叶斯算法。特征的可能性(即概率)假设为高斯分布:
参数 和 使用最大似然法估计。
-
多项分布朴素贝叶斯
MultinomialNB
实现了服从多项分布数据的朴素贝叶斯算法,也是用于文本分类的两大经典朴素贝叶斯算法之一。 分布参数由每类 的 向量决定, 式中 是特征的数量(对于文本分类,是词汇量的大小) 是样本中属于类 中特征 概率 。
参数 使用平滑过的最大似然估计法来估计,即相对频率计数:
式中 是 训练集 中 特征 在类 中出现的次数,
是类 中出现所有特征的计数总和。
先验平滑因子 应用于在学习样本中没有出现的特征,以防在将来的计算中出现0概率输出。 把 被称为拉普拉斯平滑(Lapalce smoothing),而 被称为利德斯通(Lidstone smoothing)。
-
伯努利朴素贝叶斯
BernoulliNB
实现了用于多重伯努利分布数据的朴素贝叶斯训练和分类算法,即有多个特征,但每个特征 都假设是一个二元 (Bernoulli, boolean) 变量。 因此,这类算法要求样本以二元值特征向量表示;如果样本含有其他类型的数据, 一个 BernoulliNB
实例会将其二值化(取决于 binarize
参数)。
伯努利朴素贝叶斯的决策规则基于
与多项分布朴素贝叶斯的规则不同 伯努利朴素贝叶斯明确地惩罚类 中没有出现作为预测因子的特征 ,而多项分布分布朴素贝叶斯只是简单地忽略没出现的特征。
在文本分类的例子中,词频向量(word occurrence vectors)(而非词数向量(word count vectors))可能用于训练和用于这个分类器。 BernoulliNB
可能在一些数据集上可能表现得更好,特别是那些更短的文档。 如果时间允许,建议对两个模型都进行评估。
from sklearn.datasets import load_iris
from sklearn.naive_bayes import GaussianNB,MultinomialNB, BernoulliNB # 可替换分类器
iris= load_iris()
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print("Number of mislabeled points out of a total %d points : %d" %(iris.data.shape[0],(iris.target != y_pred).sum()))