请和我一起学习机器学习算法之朴素贝叶斯
1. 朴素贝叶斯概念
- 贝叶斯公式
由条件概率: P ( A , B i ) = P ( A ∣ B i ) ⋅ P ( B i ) = P ( B i ∣ A ) ⋅ P ( A ) P(A,B_i)=P(A|B_i) \cdot P(B_i)=P(B_i|A) \cdot P(A) P(A,Bi)=P(A∣Bi)⋅P(Bi)=P(Bi∣A)⋅P(A)
(条件概率表示已知条件发生的情况下的概率,比如“P(好学生|性别女)”表示在女生的范围内好学生的概率)
可得到贝叶斯常规型:
P ( A ∣ B i ) = P ( B i ∣ A ) ⋅ P ( A ) P ( B i ) P(A|B_i)=\frac{P(B_i|A) \cdot P(A)}{P(B_i)} P(A∣Bi)=P(Bi)P(Bi∣A)⋅P(A)
全概率公式如下, B 1 , B 2 , . . . B n B_1,B_2,...B_n B1,B2,...Bn表示样本空间的一个划分。
P ( A ) = ∑ i = 1 n P ( A ∣ B i ) P ( B i ) P(A)= \sum_{i=1}^n P(A|B_i)P(B_i) P(A)=i=1∑nP(A∣Bi)P(Bi)
举个例子,A表示黄种人, B 1 B_1 B1表示男人, B 2 B_2 B2表示女人, B 3 B_3 B3表示双性人。
这个全概率公式的意思就是,黄种人的概率表示黄种男人的概率+黄种女人的概率+黄种双性人的概率。
全概率和贝叶斯常规型结合可得贝叶斯定理:
P
(
B
i
∣
A
)
=
P
(
A
∣
B
i
)
P
(
B
i
)
P
(
A
)
=
P
(
A
∣
B
i
)
P
(
B
i
)
∑
i
=
1
n
P
(
A
∣
B
i
)
P
(
B
i
)
P(B_i|A)=\frac{P(A|B_i)P(B_i)}{P(A)}=\frac{P(A|B_i)P(B_i)}{\sum_{i=1}^n P(A|B_i)P(B_i)}
P(Bi∣A)=P(A)P(A∣Bi)P(Bi)=∑i=1nP(A∣Bi)P(Bi)P(A∣Bi)P(Bi)
- 朴素
朴素的意思就是样本属性相对独立互不影响且同等重要。
如果考虑样本之间的影响,则称为贝叶斯网,或者叫信念贝叶斯。
2. 朴素贝叶斯分类
用数学语言描述为:假定有一组训练样本
X
=
{
x
1
,
x
2
,
.
.
.
,
x
m
}
X=\{x_1,x_2,...,x_m\}
X={x1,x2,...,xm}包含m个数据集合,其中每一个样本包含
l
l
l个样本属性
A
=
{
a
1
,
a
2
,
.
.
.
,
a
l
}
A=\{a_1,a_2,...,a_l\}
A={a1,a2,...,al},这些样本可以分为n类
K
=
{
k
1
,
k
2
,
.
.
.
,
k
n
}
K=\{k_1,k_2,...,k_n\}
K={k1,k2,...,kn},现在有一个样本
x
,
x
x,x
x,x不属于X,如何对
x
x
x进行分类?
这个问题是,
x
x
x已知的情况下,对于各个类别的概率的计算问题。
P
(
k
i
∣
x
)
=
P
(
x
∣
k
i
)
P
(
k
i
)
P
(
x
)
P(k_i|x)=\frac{P(x|k_i)P(k_i)}{P(x)}
P(ki∣x)=P(x)P(x∣ki)P(ki)
这个公式就是表示
x
x
x属于类别
k
i
k_i
ki的概率,如果我们能够选出一个i 使得上面的式子在所有种类中概率最大,则我们认为
x
x
x属于i类别的可能性最大,种类判断为
k
i
k_i
ki.
所以问题转换为求得不同得i下上面式子得条件概率得大小对比。
- 我们注意到,对于所有得种类上面式子得分母都相同,则对比时可以直接对比分子。实际上,我们也无法计算出这个值。
- 对于分子中得后面一项 P ( k i ) P(k_i) P(ki)我们可以通过样本数据中种类为 k i k_i ki得所占频率来估计。
- 对于分子中得前面一项,
P
(
x
∣
k
i
)
=
P
(
(
a
1
x
,
a
2
x
,
.
.
.
,
a
l
x
)
∣
k
i
)
P(x|k_i)=P((a_{1x},a_{2x},...,a_{lx})|k_i)
P(x∣ki)=P((a1x,a2x,...,alx)∣ki),根据朴素中得独立性,可以进一步为:
P
(
(
a
1
x
,
a
2
x
,
.
.
.
,
a
l
x
)
∣
k
i
)
=
∏
i
=
1
l
P
(
a
i
x
∣
k
i
)
P((a_{1x},a_{2x},...,a_{lx})|k_i)=\prod_{i=1}^{l}P(a_{ix}|k_i)
P((a1x,a2x,...,alx)∣ki)=∏i=1lP(aix∣ki),
P
(
a
i
x
∣
k
i
)
P(a_{ix}|k_i)
P(aix∣ki)表示在种类
k
i
k_i
ki中,属性值
a
i
x
a_{ix}
aix所占得概率,可以通过样本数据集合中来估算。
第三步不好理解, P ( x ∣ k i ) P(x|k_i) P(x∣ki)的意思是种类已知的情况下, x x x出现的概率。什么意思呢, P ( x ∣ k 1 ) P(x|k_1) P(x∣k1)说的就是说第一个种类下,样本x 出现的概率。因为朴素贝叶斯属性相互独立,第一个种类下样本x 出现的概率可以转为 样本x 各个属性在第一个类别下同时出现的概率。
我们通过上面得方法和步骤,我们可以获得所有种类对应得条件概率得分子值,在分母相同得情况下,可以选择出条件概率最大得种类,从而做出分类决策。
实际上,朴素贝叶斯的训练就是为了获得这些条件概率值。
3 朴素贝叶斯特殊处理
- 概率零值
拉普拉斯修正:分子+1,分母+当前属性可能的种类 - 连续值
概率密度函数计算概率。先假定某种分布,使用样本计算出参数。
4 朴素贝叶斯优缺点
- 优点
样本数据较少时有效,可处理多类别的问题。 - 缺点
对于输入数据的准备方式敏感。 - 适用数据类型
标称型数据
5 简单例子程序
获得这些条件概率值
import numpy as np
def loadDataSet():
spamList = [['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['stop','posting', 'stupid', 'worthless', 'garbage'],
['quit', 'buying', 'worthless', 'dog', 'food', 'stupid']]
hamList = [['my', 'dog', 'has', 'flea', 'problems', 'help', 'please'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'] ]
return spamList,hamList
def getVocabList(spamList,hamList):
vocabSet = set([])
for doc in spamList:
vocabSet = vocabSet | set(doc)
for doc in hamList:
vocabSet = vocabSet | set(doc)
return list(vocabSet)
def getVector_Vocab2File(datalist,vocabList):
Vec = [0]*(len(vocabList))
for data in datalist:
if data in vocabList:
Vec[vocabList.index(data)] =1
return Vec
def NavieBayesTrainForSpam(dataMatrix,labelsList):
dimension = len(labelsList)
pk1 = np.sum(labelsList)/float(dimension)
pk0 = 1-pk1
p0 = np.zeros(len(dataMatrix[0]))
p1 = np.zeros(len(dataMatrix[0]))
for i in range(dimension):
if labelsList[i] == 1:
p1 += dataMatrix[i]
else:
p0 += dataMatrix[i]
p1_res = p1/float(np.sum(labelsList))
p0_res = p0/float(dimension-np.sum(labelsList))
return p0_res,p1_res,pk0,pk1
if __name__=='__main__':
spamList,hamList = loadDataSet()
vocabList = getVocabList(spamList,hamList)
print(vocabList)
matrx = []
labelsList = []
for spam in spamList:
matrx.append(getVector_Vocab2File(spam,vocabList))
labelsList.append(1)
for ham in hamList:
matrx.append(getVector_Vocab2File(ham,vocabList))
labelsList.append(0)
print(matrx)
p0_res,p1_res,pk0,pk1 = NavieBayesTrainForSpam(matrx,labelsList)
print(p0_res)
print(p1_res)
print(pk0)