【机器学习】朴素贝叶斯实战
1. 贝叶斯公式
P ( B i ∣ A ) = P ( B i ) P ( A ∣ B i ) ∑ j = 1 n P ( B j ) P ( A ∣ B j ) ( i = 1 , 2 , … , n ) P\left(B_{i} \mid A\right)=\frac{P\left(B_{i}\right) P\left(A \mid B_{i}\right)}{\sum_{j=1}^{n} P\left(B_{j}\right) P\left(A \mid B_{j}\right)}(i=1,2, \ldots, n) P(Bi∣A)=∑j=1nP(Bj)P(A∣Bj)P(Bi)P(A∣Bi)(i=1,2,…,n)
**意义:**在事件A已经发生的条件下,贝叶斯公式可用来寻找导致A发生的各种原因B的概率。
2. 朴素贝叶斯分类器
由贝叶斯公式可以推断朴素贝叶斯分类器是一个生成式模型(建立条件概率模型用于求解最大化后验模型)。
下面举例说明朴素贝叶斯分类器的计算过程。
-
计算先验概率(结果)和条件概率
-
样例判别,根据先验类别逐一计算验证
注意:当遇到连续型数据时通过高斯分布计算
f ( x ) = 1 2 π σ exp ( − ( x − μ ) 2 2 σ 2 ) f(x)=\frac{1}{\sqrt{2 \pi} \sigma} \exp \left(-\frac{(x-\mu)^{2}}{2 \sigma^{2}}\right) f(x)=2πσ1exp(−2σ2(x−μ)2)
注意:训练集中属性值未出现的情况下要进行“拉普拉斯修正”
P ^ ( c ) = ∣ D c ∣ + 1 ∣ D ∣ + N P ^ ( x i ∣ c ) = ∣ D c , x i ∣ + 1 ∣ D ∣ + N i \hat{P}(c)=\frac{\left|D_{c}\right|+1}{|D|+N} \quad \hat{P}\left(x_{i} \mid c\right)=\frac{\left|D_{c, x_{i}}\right|+1}{|D|+N_{i}} P^(c)=∣D∣+N∣Dc∣+1P^(xi∣c)=∣D∣+Ni∣Dc,xi∣+1
注意:当属性数量多的情况下,导致累乘结果下溢。采用防溢出策略(累乘变累加)
ln ( a ∗ b ) = ln ( a ) + ln ( b ) \ln \left(a^{*} b\right)=\ln (a)+\ln (b) ln(a∗b)=ln(a)+ln(b)
3. 垃圾邮件分类
计算每种结果出现的概率:
P
(
S
p
a
m
)
=
2
5
P
(
H
a
m
)
=
3
5
P(Spam)=\frac{2}{5}\\ P(Ham)=\frac{3}{5}
P(Spam)=52P(Ham)=53
计算每个词条属性出现的概率(属性所属类别中该属性出现的次数➗属性所属类别出现的词条总数):
P
(
c
h
a
n
n
e
l
∣
S
p
a
m
)
=
2
8
P
(
c
h
a
n
n
e
l
∣
H
a
m
)
=
2
8
P
(
c
h
e
c
k
∣
S
p
a
m
)
=
1
8
P
(
c
h
e
c
k
∣
H
a
m
)
=
2
8
P
(
f
a
n
∣
S
p
a
m
)
=
0
8
P
(
f
a
n
∣
H
a
m
)
=
2
8
P
(
g
r
e
a
t
∣
S
p
a
m
)
=
0
8
P
(
g
r
e
a
t
∣
H
a
m
)
=
2
8
P
(
l
i
k
e
∣
S
p
a
m
)
=
1
8
P
(
l
i
k
e
∣
H
a
m
)
=
2
8
P
(
l
o
v
e
∣
S
p
a
m
)
=
1
8
P
(
l
o
v
e
∣
H
a
m
)
=
2
8
P
(
s
o
n
g
∣
S
p
a
m
)
=
2
8
P
(
s
o
n
g
∣
H
a
m
)
=
2
8
P
(
t
u
b
e
∣
S
p
a
m
)
=
1
8
P
(
t
u
b
e
∣
H
a
m
)
=
2
8
P(channel|Spam)=\frac{2}{8} \quad P(channel|Ham)=\frac{2}{8}\\ P(check|Spam)=\frac{1}{8}\quad P(check|Ham)=\frac{2}{8}\\ P(fan|Spam)=\frac{0}{8} \quad P(fan|Ham)=\frac{2}{8}\\ P(great|Spam)=\frac{0}{8} \quad P(great|Ham)=\frac{2}{8}\\ P(like|Spam)=\frac{1}{8} \quad P(like|Ham)=\frac{2}{8}\\ P(love|Spam)=\frac{1}{8} \quad P(love|Ham)=\frac{2}{8}\\ P(song|Spam)=\frac{2}{8} \quad P(song|Ham)=\frac{2}{8}\\ P(tube|Spam)=\frac{1}{8} \quad P(tube|Ham)=\frac{2}{8}
P(channel∣Spam)=82P(channel∣Ham)=82P(check∣Spam)=81P(check∣Ham)=82P(fan∣Spam)=80P(fan∣Ham)=82P(great∣Spam)=80P(great∣Ham)=82P(like∣Spam)=81P(like∣Ham)=82P(love∣Spam)=81P(love∣Ham)=82P(song∣Spam)=82P(song∣Ham)=82P(tube∣Spam)=81P(tube∣Ham)=82
以love song为例:
P
(
S
p
a
m
∣
l
o
v
e
s
o
n
g
)
=
2
5
×
1
8
×
2
8
=
1
80
P
(
H
a
m
∣
l
o
v
e
s
o
n
g
)
=
3
5
×
2
8
×
2
8
=
3
80
3
80
>
1
80
所
以
类
别
为
H
a
m
P(Spam|love song) = \frac{2}{5} \times \frac{1}{8} \times \frac{2}{8}=\frac{1}{80}\\ P(Ham|love song) = \frac{3}{5} \times \frac{2}{8} \times \frac{2}{8}=\frac{3}{80}\\ \frac{3}{80}>\frac{1}{80}\\ 所以类别为Ham
P(Spam∣lovesong)=52×81×82=801P(Ham∣lovesong)=53×82×82=803803>801所以类别为Ham
核心代码:
链接:https://pan.baidu.com/s/1L5VnzRLX06CZkBzXicMUDw
提取码:ima9
"""
函数说明:朴素贝叶斯分类器训练函数
Parameters:
trainMatrix - 训练文档矩阵,即setOfWords2Vec返回的returnVec构成的矩阵
trainCategory - 训练类别标签向量,即loadDataSet返回的classVec
Returns:
p0Vect - 正常邮件类的条件概率数组
p1Vect - 垃圾邮件类的条件概率数组
pAbusive - 文档属于垃圾邮件类的概率
"""
def trainNB0(trainMatrix, trainCategory):
numTrainDocs = len(trainMatrix) # 计算训练的文档数目
print("文档数目:", numTrainDocs)
numWords = len(trainMatrix[0]) # 计算每篇文档的词条数
print("词条数", numWords)
print("---:", trainCategory)
# 形状[40,37]
print("---:", trainMatrix)
pAbusive = sum(trainCategory) / float(numTrainDocs) # 文档属于垃圾邮件类的概率
p0Num = np.ones(numWords)
p1Num = np.ones(numWords) # 创建numpy.ones数组,词条出现数初始化为1,拉普拉斯平滑
p0Denom = 2.0
p1Denom = 2.0 # 分母初始化为2 ,拉普拉斯平滑
for i in range(numTrainDocs):
if trainCategory[i] == 1: # 统计属于侮辱类的条件概率所需的数据,即P(w0|1),P(w1|1),P(w2|1)···
print("p1Num",p1Num)
p1Num += trainMatrix[i]
print("p1Denom",p1Denom)
p1Denom += sum(trainMatrix[i])
else: # 统计属于非侮辱类的条件概率所需的数据,即P(w0|0),P(w1|0),P(w2|0)···
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
print("1:",p1Num / p1Denom)
print("0:",p0Num / p1Denom)
p1Vect = np.log(p1Num / p1Denom)
p0Vect = np.log(p0Num / p0Denom) #取对数,防止下溢出
return p0Vect, p1Vect, pAbusive # 返回属于正常邮件类的条件概率数组,属于侮辱垃圾邮件类的条件概率数组,文档属于垃圾邮件类的概率
"""
函数说明:朴素贝叶斯分类器分类函数
Parameters:
vec2Classify - 待分类的词条数组
p0Vec - 正常邮件类的条件概率数组
p1Vec - 垃圾邮件类的条件概率数组
pClass1 - 文档属于垃圾邮件的概率
Returns:
0 - 属于正常邮件类
1 - 属于垃圾邮件类
"""
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
p1=sum(vec2Classify*p1Vec)+np.log(pClass1)
p0=sum(vec2Classify*p0Vec)+np.log(1.0-pClass1)
if p1 > p0:
return 1
else:
return 0