BitTigerio 2018-05-20
对于给定的训练数据,首先基于特征条件独立假设学习输入/输出的联合概率分布,然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。
条件概率应该比较熟悉,P(A|B) 表示事件B已经发生的条件下,事件A发生的概率。计算公式如下:
事件的独立性:
假设 A,B是两个事件,如果满足等式: P(AB) = P(A)*P(B) ,则称时间A,B相互独立.
由条件概率公式知:如果两个事件独立则: P(A|B) = P(A) . (B的发生与否对于A的结果没有影响)
参数(随机变量)的独立性:
假设(x1,x2)是二位的随机变量,其联合分布函数为F(x1,x2),随机变量x1,x2的边缘分布函数为Fx1(x1)和Fx2(x2),如果对于任意x1,x2均有:
F(x1,x2) = Fx1(x1) * Fx2(x2)
该公式等价于: P{X1<x1,X2<x2} = P{X1<x1} * P{X2<x2}
则 x1, x2为相互独立的随机变量
在建模时,往往涉及到选取不同的特征变量(如颜色形状等等),这些参数的独立就是这里的参数独立。
先验概率(prior probability)是指根据以往经验和分析得到的概率,如全概率公式,它往往作为"由因求果"问题中的"因"出现的概率。
用处:极大似然估计往往用来计算一个模型中的参数。 使用前提:“模型已定,参数未知”
原理:通过微分(如果有多个参数,可能需要解微分方程组)的方法寻找使样本集合(x1,x2,x3,x4…..)出现概率最大的模型参数。下面是概率论中通过极大似然估计,计算高斯分布的两个参数:(实际中的模型往往比高斯模型复杂的多,但是原理是一样的)
至于为什么一阶导数得到的方程组就能求得极大值,请参考这篇文章:http://www.cnblogs.com/hapjin/p/6633471.html
最大似然估计的一般求解过程:
(1) 写出似然函数;
(2) 对似然函数取对数,并整理;
(3) 求导数 ;
(4) 解似然方程
假如一个样本的输入为X(可以为一个向量x1,x2,x3…),输出为Y(可以是分类问题,也可以是连续值)
假设: 条件独立性假设:用于分类的特征在类确定额条件下都是条件独立的。
朴素贝叶斯法通过训练数据集学习联合概率分布P(X,Y)。
先验概率: P(Y)
条件概率: P(X = x|Y = y)
条件独立性假设:
最终得到后验概率的计算公式(4.4) 及 贝叶斯分类器的计算公式(4.7)
注: 分母做了归一下处理(比较双方分母都化作1)
1. 邮件分为两类,一种为正常邮件,另一种为侮辱性邮件(标签分别用 0/1表示 )
2. 提供 正常邮件和侮辱性邮件(数据及其标签)
3. 当输入邮件数据时,系统需要输出其标签
1. 加载邮件数据以及他们的标签(邮件分类:是否为恶意邮件)
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 abusive, 0 not return postingList,classVec
2. 基于已有的邮件构建”单词表“(所有邮件中包含的单词)
def createVocabList(dataSet): vocabSet = set([]) #create empty set for document in dataSet: vocabSet = vocabSet | set(document) #union of the two sets return list(vocabSet)
3. 将已有的邮件映射到词表中(如果邮件中某个单词出现则此表中该 位置为 1 否则为0)
def setOfWords2Vec(vocabList, inputSet): 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
将预处理好的数据输入到该函数中,就能得到上面公式4.7中: P(x=xi | Y=1)或者 P(x=xi | Y=0) 的每项概率保存在返回的两个数组。并且将 整体 的概率 P(Y=1) 也返回了。
# trainMatrix: 文本映射到“词表”中的矩阵 # trainCategory: 文本的 类别 def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) # 文本的数量 numWords = len(trainMatrix[0]) # 词表的长度 pAbusive = sum(trainCategory)/float(numTrainDocs) # 类别为1的概率 p0Num = ones(numWords); # 存放计算的条件概率 P(xi|Y=0) p1Num = ones(numWords) # 存放计算的条件概率 P(xi|Y=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) #change to log() p0Vect = log(p0Num/p0Denom) #change to log() return p0Vect,p1Vect,pAbusive
根据贝叶斯公式分别计算一封邮件是正常邮件还是侮辱性邮件的概率,如下所示:
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1): p1 = sum(vec2Classify * p1Vec) + log(pClass1) #element-wise mult p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1) if p1 > p0: return 1 else: return 0
参考:
《机器学习实战》
《统计学方法》