贝叶斯定理与情感分析
概率模型
从条件概率公式推导出贝叶斯
从条件概率公式
[math]\displaystyle{ P(A|B) P(B) =P(A \cap B) =P(B|A) P(A) }[/math]
可以得到贝叶斯公式
[math]\displaystyle{ P(B|A) = \frac{P(B)P(A|B)}{P(A)} }[/math]
语义模型贝叶斯
在情感分析中的语义模型,就是为了把文本根据特征(例如切成token的一个个词)进行分类。由特征的属性(正面还是负面)决定文本的属性。
假设我们有
Variable | Values | Meaning |
---|---|---|
C | "pos","neg" | 单条Tweet 分类 |
F1 | "non-neg" | 单条Tweet中"awesome"个数 |
F2 | "non-neg" | 单条Tweet中"crasy"个数 |
现在,我们的问题是,如果看到了F1和F2这两个特征,单条tweet属于类别C的概率是多少?贝叶斯模型对这个问题的回答如下:
[math]\displaystyle{ P(C|F_1,F_2) = \frac{P(C)P(F_1,F_2|C)}{P(F_1,F_2)} }[/math]
公式左边的三个变量都是可以从采集的数据集(训练集)中获得的。P(c)就是数据集中某一类(例如pos)tweets的出现概率,我们用它代替真实的 总体概率;P(F_1,F_2)就是数据集中包含F1个"awesome"和F2个"crazy"的tweet的个数;至于P(F_1,F_2|C),我们可以直接数某一类tweets中同时包含F1个"awesome"和F2个"crazy"的tweet的个数—这种做法在数据集比较小的时候并不明智,也可以通过假设F1和F2相互独立,从而得到
[math]\displaystyle{ P(F_1,F_2|C) = P(F_1|C)P(F_2|F_1,C)= P(F_1|C)P(F_2|C) }[/math]
因为引入了特征相互独立的假设,所以叫“朴素”贝叶斯(Naive Bayesian),看起来这个假设很简单粗暴,但这个模型却在真实世界中非常好用, 一点也不“朴素”。
综合以上分析,我们的“朴素”贝叶斯模型就是
[math]\displaystyle{ P(C|F_1,F_2) = \frac{P(C)P(F_1|C)P(F_2|C)}{P(F_1,F_2)} }[/math]
总结一下,贝叶斯模型使得我们可以使用已知的信息来猜测未知的信息,其逻辑是
[math]\displaystyle{ posterior = \frac{prior * likelihood}{evidence} }[/math]
对语义模型贝叶斯经行调整
现在,我们已经有了一个可以工作的模型,但要应用的真实数据集上还存在两个问题
1.P(F_1,F_2)可能等于0;
2.P(F_1|C)P(F_2|C)的概率可能会很小,超出像python numpy这种包的定义范围,以至需要特殊的包。
解决第一个问题的方案是对概率进行修正,具体办法是对于每一个概率,分子加1分母加d(d是特征数,这里就是2);解决第二个问题的办法是使用对数概率代替概率。使用对数概率后,原有的朴素贝叶斯公式变为
[math]\displaystyle{ log P(C|F_1,F_2) = log P(C) + log P(F_1|C) + log P(F_2|C)- log P(F_1,F_2) }[/math]
因为在对单条tweet进行判别时,仅仅最后一项是常数,所以我们只关心前面一项。当然,两条特征是远不足以判别的,所以真实公式是
[math]\displaystyle{ log P(C|F_1,F_2) = log P(C) + \sum_{i=1}^{k} log P(F_k|C) }[/math]
Python 代码及示例:使用朴素贝叶斯模型判别论坛帖子是否辱骂性
调用模块
from numpy import *
代码示例
#------revised from http://blog.csdn.net/marvin521/article/details/9262445
from numpy import *
#----------1. prepare trainning set------------
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. define feature space/tokenize function----------
def createVocabList(dataSet):
vocabSet = set([])
for document in dataSet:
vocabSet = vocabSet | set(document)
return list(vocabSet)
#---------3. function to project test data in the feature space-------
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. function to train a naive Bayesian model from the training data set----
def trainNB0(trainMatrix,trainCategory):
NdataPoints = len(trainCategory)
featureSpaceDimensions = len(trainMatrix[0])
pAbusive = sum(trainCategory)*1.0/len(trainCategory)
p0Num = ones(featureSpaceDimensions); p1Num = ones(featureSpaceDimensions) # zeros change to ones()
p0Denom = 2.0; p1Denom = 2.0 #1.0 change to 2.0
for i in range(NdataPoints):
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
#------------5. Applied the trained model to classify posts (projected in the feature space)--------
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
#---------------------- test----------------
d1=loadDataSet()
featureSpace=createVocabList(d1[0])
examplePost=re.split(" ", "I love my dog and my family")
exampleVector=setOfWords2Vec(featureSpace,examplePost)
trainMatrix=map(lambda x:setOfWords2Vec(featureSpace,x),d1[0])
trainCategory=d1[1]
p0Vect,p1Vect,pAbusive = trainNB0(trainMatrix,trainCategory)
classifyNB(exampleVector, p0Vect, p1Vect, pAbusive)