首先我们先回顾下理论部分,本文依然采用NLTK中的twitter corpus进行情感分类的二分类:positive和negative。
在inference时需要计算
P
(
p
o
s
)
P
(
n
e
g
)
∏
i
=
0
m
P
(
w
i
∣
p
o
s
)
P
(
w
i
∣
n
e
g
)
\frac{P(pos)}{P(neg)}\prod_{i=0}^m\frac{P(w_i|pos)}{P(w_i|neg)}
P(neg)P(pos)∏i=0mP(wi∣neg)P(wi∣pos)(定义
r
a
t
i
o
=
P
(
w
i
∣
P
o
s
)
P
(
w
i
∣
N
e
g
)
ratio=\frac{P(w_i|Pos)}{P(w_i|Neg)}
ratio=P(wi∣Neg)P(wi∣Pos),如果>1则该条tweet为positive,=1则为中性,<1则为negative)。
但是句子长度越长导致计算下溢,我们引入
l
o
g
log
log计算:
λ
(
w
)
=
l
o
g
P
(
w
i
∣
P
o
s
)
P
(
w
i
∣
N
e
g
)
\lambda(w)=log\frac{P(w_i|Pos)}{P(w_i|Neg)}
λ(w)=logP(wi∣Neg)P(wi∣Pos)。因此。最后的计算公式变成
l
o
g
(
P
(
p
o
s
)
P
(
n
e
g
)
∏
i
=
0
m
P
(
w
i
∣
p
o
s
)
P
(
w
i
∣
n
e
g
)
)
=
l
o
g
P
(
p
o
s
)
P
(
n
e
g
)
+
∑
i
=
0
m
l
o
g
P
(
w
i
∣
p
o
s
)
P
(
w
i
∣
n
e
g
)
=
l
o
g
p
r
i
o
r
+
∑
i
=
0
m
l
o
g
l
i
k
e
l
i
h
o
o
d
=
l
o
g
p
r
i
o
r
+
∑
i
=
0
m
λ
log(\frac{P(pos)}{P(neg)}\prod_{i=0}^m\frac{P(w_i|pos)}{P(w_i|neg)}) =log\frac{P(pos)}{P(neg)} + \sum_{i=0}^mlog\frac{P(w_i|pos)}{P(w_i|neg)} =logprior + \sum_{i=0}^{m}loglikelihood=logprior + \sum_{i=0}^{m}\lambda
log(P(neg)P(pos)∏i=0mP(wi∣neg)P(wi∣pos))=logP(neg)P(pos)+∑i=0mlogP(wi∣neg)P(wi∣pos)=logprior+∑i=0mloglikelihood=logprior+∑i=0mλ。(如果>0则该条tweet为positive,=0则为中性,<0则为negative。)
所以总结下整个过程大致为:获取数据集、预处理、计算
f
r
e
q
(
w
i
,
c
l
a
s
s
)
freq(w_i,class)
freq(wi,class),计算
r
a
t
i
o
ratio
ratio,计算
λ
\lambda
λ,计算
l
o
g
p
r
i
o
r
logprior
logprior。
具体代码实现见:GitHub源码
错误分析
预处理时移除了标点符号
预处理时忽略了否定
忽略了词顺序
讽刺委婉的表达
总结
朴素贝叶斯(NB)基于条件独立性假设和语料库中的词频来进行实现。一方面,朴素贝叶斯是一个非常简单的模型,因为它不需要设置自定义任何参数;另一方面,朴素贝叶斯也有如下问题。
- NB假设一段文本中的word相互独立,但在现实中往往不是这样。这会导致单个word的估计值低于或高于真实值。
在左图中,“sunny”和“hot”似乎是相互关联并且一定程度上和“desert”相关。而NB会给右图中中的word filling任务中“spring, summer, fall, winter”四个候选词相等的概率。显然这是不合理的。
- NB的另一个问题是依赖训练集的分布。一个好的数据集应该包含相同比例的正例和负例。大多数可用的标注数据集都是人为平衡的。但在现实的推文流中,发送正面推文的频率大于负面推文的频率。原因之一是负面推文可能包含平台禁止或用户忽略的内容。也就是现实中的数据集会有更多噪声。
总结就是朴素贝叶斯的独立性假设很难得到保证,但是尽管如此该模型在某些情况下仍然运行良好。对于模型的训练,需要平衡训练数据集中正例和负例的相对频率,以便提供准确的结果。