机器学习--朴素贝叶斯
1- 贝叶斯定理
用来描述两个条件概率之间的关系.
贝叶斯公式: P ( A ∣ B ) = P ( B ∣ A ) ∗ P ( A ) / P ( B ) 形式转换: P ( A ∩ B ) = P ( A B ) = P ( B ∣ A ) ⋅ P ( A ) = P ( A ∣ B ) ⋅ P ( B ) 贝叶斯公式:P(A|B)=P(B|A)*P(A)/P(B)\\形式转换:P(A∩B) =P(AB)=P(B|A)·P(A)=P(A|B)·P(B) 贝叶斯公式:P(A∣B)=P(B∣A)∗P(A)/P(B)形式转换:P(A∩B)=P(AB)=P(B∣A)⋅P(A)=P(A∣B)⋅P(B)
2- 贝叶斯法则
通常,事件A在事件B(发生)的条件下的概率,与事件B在事件A的条件下的概率是不一样的;然而,这两者是有确定的关系,贝叶斯法则就是这种关系的陈述。
贝叶斯法则 : 是关于事件 A 和事件 B 的条件概率和边缘概率的。 P ( A i ∣ B ) = P ( B ∣ A i ) ⋅ P ( A i ) ∑ j n P ( B ∣ A j ) ⋅ P ( A j ) 贝叶斯法则:是关于事件A和事件B的条件概率和边缘概率的。\\ P(A_i|B)=\frac{P(B|A_i)·P(A_i)}{\sum_j^nP(B|A_j)·P(A_j)} 贝叶斯法则:是关于事件A和事件B的条件概率和边缘概率的。P(Ai∣B)=∑jnP(B∣Aj)⋅P(Aj)P(B∣Ai)⋅P(Ai)
- P(A|B):是在B发生的情况下A发生的可能性。1—An 事件组
- P(A) 是A的先验概率或边缘概率。之所以称为"先验"是因为它不考虑任何B方面的因素。
- P(A|B) 是已知B发生后A的条件概率,也由于得自B的取值而被称作A的后验概率。
- P(B|A) 是已知A发生后B的条件概率,也由于得自A的取值而被称作B的后验概率。
- P(B) 是B的先验概率或边缘概率,也作标准化常量(normalized constant)。
2-1 - 贝式定理
当变量是超过 2 个以上,依然成立: P ( A ∣ B , C ) = P ( A ) P ( B ∣ A ) ⋅ P ( C ∣ A , B ) P ( B ) ⋅ P ( C ∣ B ) 当变量是超过2个以上,依然成立:\\P(A|B,C)=\frac{P(A)P(B|A)·P(C|A,B)}{P(B)·P(C|B)} 当变量是超过2个以上,依然成立:P(A∣B,C)=P(B)⋅P(C∣B)P(A)P(B∣A)⋅P(C∣A,B)
2-2 - 概率案列
我们通过两个案列来来理解下公式的运用:
案例
1
:假设小偷
1
和小偷
2
在某村庄的作案数量比为
3
:
2
,
前者偷窃成功的概率
0.02
,后者
0.01
,先村庄失窃。
求这次失窃是小偷
1
作案的概率。
设:失窃事件为
A
,小偷
B
1
,
2
s
o
l
v
e
:
由题意
P
(
B
1
)
=
3
5
,
P
(
B
2
)
=
2
5
,
P
(
A
∣
B
1
)
=
0.02
,
P
(
A
∣
B
2
)
=
0.01
求:
P
(
B
1
∣
A
)
贝叶斯:
P
(
B
i
∣
A
)
=
P
(
A
∣
B
i
)
⋅
P
(
B
i
)
∑
j
n
P
(
A
∣
B
j
)
⋅
P
(
B
j
)
P
(
B
1
∣
A
)
=
P
(
A
∣
B
1
)
⋅
P
(
B
1
)
∑
j
2
P
(
A
∣
B
j
)
⋅
P
(
B
j
)
=
0.02
∗
3
5
0.02
∗
3
5
+
0.01
∗
2
5
=
0.75
案例1:假设小偷1和小偷2在某村庄的作案数量比为3:2,前者偷窃成功的概率0.02,后者0.01,先村庄失窃。\\求这次失窃是小偷1作案的概率。\\ 设:失窃事件为A,小偷B_{1,2}\\ solve: 由题意 P(B_1)=\frac{3}{5},P(B_2)=\frac{2}{5},P(A|B_1)=0.02,P(A|B_2)=0.01\\ 求:P(B_1|A)\\ 贝叶斯:P(B_i|A)=\frac{P(A|B_i)·P(B_i)}{\sum_j^nP(A|B_j)·P(B_j)}\\ P(B_1|A)=\frac{P(A|B_1)·P(B_1)}{\sum_j^2P(A|B_j)·P(B_j)}\\ =\frac{0.02*\frac{3}{5}}{0.02*\frac{3}{5}+0.01*\frac{2}{5}}\\=0.75
案例1:假设小偷1和小偷2在某村庄的作案数量比为3:2,前者偷窃成功的概率0.02,后者0.01,先村庄失窃。求这次失窃是小偷1作案的概率。设:失窃事件为A,小偷B1,2solve:由题意P(B1)=53,P(B2)=52,P(A∣B1)=0.02,P(A∣B2)=0.01求:P(B1∣A)贝叶斯:P(Bi∣A)=∑jnP(A∣Bj)⋅P(Bj)P(A∣Bi)⋅P(Bi)P(B1∣A)=∑j2P(A∣Bj)⋅P(Bj)P(A∣B1)⋅P(B1)=0.02∗53+0.01∗520.02∗53=0.75
案例 2 :例如:一座别墅在过去的 20 年里一共发生过 2 次被盗,别墅的主人有一条狗,狗平均每周晚上叫 3 次, 在盗贼入侵时狗叫的概率被估计为 0.9 ,问题是:在狗叫的时候发生入侵的概率是多少? s t e p 1 : 设事件狗叫为事件 A ,盗贼入侵为事件 B ,求 P ( B ∣ A ) s t e p 2 : P ( A ) = 3 7 , P ( B ) = 2 20 ∗ 365 , P ( A ∣ B ) = 0.9 s t e p 3 : P ( B ∣ A ) = p ( B ) ∗ P ( A ∣ B ) ∑ i n P ( A ∣ B i ) ∗ P ( B i ) = p ( B ) ∗ P ( A ∣ B ) P ( A ) = 0.00058 案例2: 例如:一座别墅在过去的 20 年里一共发生过 2 次被盗,别墅的主人有一条狗,狗平均每周晚上叫 3 次,\\在盗贼入侵时狗叫的概率被估计为 0.9,问题是:在狗叫的时候发生入侵的概率是多少?\\ step1:设事件狗叫为事件A,盗贼入侵为事件B,求P(B|A)\\ step2:P(A)=\frac{3}{7},P(B)=\frac{2}{20*365},P(A|B)=0.9\\ step3:P(B|A)=\frac{p(B)*P(A|B)}{\sum_i^n P(A|B_i)*P(B_i)}=\frac{p(B)*P(A|B)}{P(A)}=0.00058 案例2:例如:一座别墅在过去的20年里一共发生过2次被盗,别墅的主人有一条狗,狗平均每周晚上叫3次,在盗贼入侵时狗叫的概率被估计为0.9,问题是:在狗叫的时候发生入侵的概率是多少?step1:设事件狗叫为事件A,盗贼入侵为事件B,求P(B∣A)step2:P(A)=73,P(B)=20∗3652,P(A∣B)=0.9step3:P(B∣A)=∑inP(A∣Bi)∗P(Bi)p(B)∗P(A∣B)=P(A)p(B)∗P(A∣B)=0.00058
3- 朴素贝叶斯
描述
基于贝叶斯定理与特征条件独立假设的分类方法。对于给定的训练数据集,首先基于特征条件独立假设学习输入输出的联合概率分布;然后基于此模型,对给定的输入X,利用贝叶斯定理求出后验概率最大的输出Y。
3-1 朴素贝叶斯法的参数估计
3-1-1 极大似然估计
连续分布下的概率密度函数P(x|c)
估计条件概率的一种常用策略是先假定具有某种确定的概率分布形式,再基于训练样本对概率分布的参数进行估计
令 D c 表示训练集 D 中第 c 类样本组成的集合,假设这些样本是独立同分布的,则参数 θ c 对于数据集 D c 的似然: P ( D C ∣ θ c ) = ∏ x ∈ D c P ( x ∣ θ c ) 对 θ 进行极大似然估计,就是去寻找最大化似然 P ( D c ∣ θ c ) 的参数值 θ ^ c 。 直观上看,极大似然估计是试图在 θ c 的所有可能的取值中,找出一个能使数据出现的 ∗ ∗ 可能性 ∗ ∗ " 最大值 连乘操作易造成下溢,通常使用对数似然: L L ( θ c ) = P ( D C ∣ θ c ) = ∑ x ∈ D c l o g P ( x ∣ θ c ) 此时参数 θ ^ c 为: θ ^ c = a r g m a x θ ^ c L L ( θ c ) 。 令D_c表示训练集D中第c类样本组成的集合,假设这些样本是独立同分布的,则参数θ_c对于数据集D_c的似然:\\ P(D_C|\theta_c)=\prod_{x∈D_c}P(x|\theta_c)\\ 对\theta 进行极大似然估计,就是去寻找最大化似然P(D_c|\theta_c)的参数值\hat θ_c。\\直观上看,极大似然估计是试图在\theta_c的所有可能的取值中,找出一个能使数据出现的 **可能性**"最大值\\ 连乘操作易造成下溢,通常使用对数似然:\\ LL(\theta_c)=P(D_C|\theta_c)=\sum_{{x∈D_c}}logP(x|\theta_c)\\ 此时参数\hat θ_c为:\hat θ_c=arg \space \underset {\hat θ_c}{max}\space LL(\theta_c)。 令Dc表示训练集D中第c类样本组成的集合,假设这些样本是独立同分布的,则参数θc对于数据集Dc的似然:P(DC∣θc)=x∈Dc∏P(x∣θc)对θ进行极大似然估计,就是去寻找最大化似然P(Dc∣θc)的参数值θ^c。直观上看,极大似然估计是试图在θc的所有可能的取值中,找出一个能使数据出现的∗∗可能性∗∗"最大值连乘操作易造成下溢,通常使用对数似然:LL(θc)=P(DC∣θc)=x∈Dc∑logP(x∣θc)此时参数θ^c为:θ^c=arg θ^cmax LL(θc)。
3-1-2 学习与分类算法
步骤:先计算先验概率和条件概率拆分
:
P
(
Y
=
c
k
)
∏
j
=
1
n
P
(
X
(
j
)
=
x
(
j
)
∣
Y
=
c
k
)
确定实例
x
的类别:
y
=
a
r
g
m
a
x
c
k
P
(
Y
=
c
k
)
∏
j
=
1
n
P
(
X
(
j
)
=
x
(
j
)
∣
Y
=
c
k
)
训练数据学习一个朴素贝叶斯分类器
步骤:先计算先验概率和条件概率拆分:P(Y=c_k)\prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k)\\确定实例x的类别:y=arg\space \underset {c_k}{max}P(Y=c_k)\prod_{j=1}^nP(X^{(j)}=x^{(j)}|Y=c_k)\\训练数据学习一个朴素贝叶斯分类器
步骤:先计算先验概率和条件概率拆分:P(Y=ck)j=1∏nP(X(j)=x(j)∣Y=ck)确定实例x的类别:y=arg ckmaxP(Y=ck)j=1∏nP(X(j)=x(j)∣Y=ck)训练数据学习一个朴素贝叶斯分类器
通过下列实例理解上述公式
3-1-3 贝叶斯估计
用极大似然估计可能会出现所要估计的概率为0的情况。这时会影响到后验概率的计算结果,使得分类产生偏差。解决这一问题的方法是采用贝叶斯估计,引用拉普拉斯平滑系数λ。
P
λ
(
X
(
j
)
)
=
a
j
l
∣
Y
=
C
k
)
=
∑
i
=
1
N
I
(
x
i
(
j
)
=
a
j
l
,
y
i
=
C
k
)
+
λ
∑
i
=
1
N
I
(
y
i
=
C
k
)
+
S
j
λ
P_λ(X^{(j)})=a_{jl}|Y=C_k) = \frac{\sum_{i=1}^NI(x_i^{(j)}=a_{jl},y_i=C_k)+λ} {\sum_{i=1}^NI(y_i=C_k)+S_jλ}
Pλ(X(j))=ajl∣Y=Ck)=∑i=1NI(yi=Ck)+Sjλ∑i=1NI(xi(j)=ajl,yi=Ck)+λ
当λ=0时,就是极大似然估计。
当λ=1,按照拉普拉斯平滑估计概率。
如上图:样本15种,类别1有9种,-1有6种,当加上拉普拉斯平滑系数时,正样本概率从9/15变成 10/17,负样本从6/15变成7/17。
#多项式朴素贝叶斯:
当特征是离散变量时,使用多项式模型
#高斯朴素贝叶斯:
当特征是连续变量时,使用高斯模型
#伯努利朴素贝叶斯:
伯努利模型和多项式模型是一致的,但要求特征是二值化的(1,O)注意:
当特征中既有连续变量又有离散变量时,一般将连续变量离散化后使用--多项式模型
4 代码部分
import numpy as np
"""
数据预处理,取出所有特征X和所有结果y
编写多项式模型
1、实现构造方法 ,所需属性有:λ,所有类别列表,先验概率列表,后验概率字典
2、训练数据
统计所有的类别
计算先验概率
计算后验概率:先遍历类别,在里面遍历第x特征,计算每个类别的第x特征下每一个标签的后验概率
3、预测数据
取出每一条要预测的数据t
取出每一个先验概率,计算概率 :先验概率*= t里面每个特征标签的后验概率
取出概率最大的类别
"""
# 多项式 模型
class MultinomialNB:
def __init__(self, alpha=0):
# 保存所有的类
self.classes = []
# 先验概率
self.cla_prob = []
# 后验概率
self.conditional_prob = {}
# 平滑操作,λ参数
self.alpha = alpha
# 计算后验概率
def _calculate_feature_prob(self, feature, feature_cla):
# 定义一个字典保存每一个标签的概率
value_prob = {}
feature = list(feature)
# 当前类别的数量
cla_total_num = len(feature)
# 第x个特征的标签数量 (SML就是3)
x_cla = len(feature_cla)
# 计算每一个标签的后验概率
for value in feature_cla:
value_prob[value] = (feature.count(value) + self.alpha) / (cla_total_num + self.alpha * x_cla)
return value_prob
# 训练数据,计算现验概率和后验概率
def fit(self, X, y):
# 将所有的类别保存在self.classes内
self.classes = list(set(y))
# print(self.classes)
# 计算先验概率
# 统计总共的数据条数
total_num = len(y)
# print(total_num)
for cla in self.classes:
# 统计当前类别的数量
num = list(y).count(cla)
# print(num)
# 计算当前类别的先验概率,并且添加到属性self.cla_prob里面
self.cla_prob.append((num + self.alpha) / (total_num + self.alpha * len(self.classes)))
# 计算后验概率
# 遍历每一个类别
for cla in self.classes:
# 以类别作为键,在属性self.conditional_prob里面创建键值对,值为字典
self.conditional_prob[cla] = {}
# 遍历每一个特征
for x in range(len(X[0])):
# 取出该类别里,第x个特征
feature = X[[cla == i for i in y]][:, x]
# print(cla,x,feature)
# 取出第x个特征内的所有标签
feature_cla = list(set(X[:, x]))
# 将该类别下的第x个特征的所有标签的后验概率保存在self.conditional_prob[cla][x]
self.conditional_prob[cla][x] = self._calculate_feature_prob(feature, feature_cla)
# 取出该类别下的该特征里面的target概率
def _get_xj_prob(self, value_prob, target):
return value_prob[target]
# 预测单条数据
def _predit_single_sample(self, t):
label = -1
# 列表中的每个元素都是字典,保存标签和概率
prob = []
# 分别计算每一个类的概率
for cla_index in range(len(self.classes)):
# 类别名
cla = self.classes[cla_index]
# 取出第cla_index个类别的先验概率
cla_prob = self.cla_prob[cla_index]
for x, value_prob in self.conditional_prob[cla].items():
# 取出该类别cla下的第x个特征的后验概率
cla_prob *= self._get_xj_prob(value_prob, t[x])
prob.append({'label': cla, 'prob': cla_prob})
# 以概率大小排序
prob.sort(key=lambda x: x['prob'])
# 取出概率最大的标签所在的字典
label = prob[-1]
label = label['label']
return label
# 预测结果
def predit(self, test):
labels = []
for t in test:
labels.append(self._predit_single_sample(t))
return labels
# # 数据预处理
# data = np.loadtxt('data.txt',delimiter=',',dtype=np.str,encoding='utf-8')
# # print(data)
#
# X = data[:,:-1]
# y = data[:,-1]
# # print(X)
# # print(y)
# mulNB = MultinomialNB()
# mulNB.fit(X,y)
# # print(mulNB.classes)
# # print(mulNB.cla_prob)
# # print(mulNB.conditional_prob)
# test = [['3','M'],['2','S']]
# results = mulNB.predit(test)
# print(results)
# 高斯模型
class GaussianNB(MultinomialNB):
# feature是该类别下的第x个特征的所有数据
def _calculate_feature_prob(self, feature, feature_cla):
feature = feature.astype(np.float)
# print(feature)
# print(type(feature))
mu = feature.mean()
sigma = np.std(feature, ddof=1)
return mu, sigma
# 取出该类别下的该特征里面的target概率
def _get_xj_prob(self, value_prob, target):
mu, sigma = value_prob
return (1 / (np.sqrt(2 * np.pi) * sigma)) * np.exp(-(((float(target) - mu) ** 2) / (2 * sigma ** 2)))
data = np.loadtxt('iris.txt',delimiter=',',dtype=np.str,encoding='utf-8')
X = data[:,:-1]
y = data[:,-1]
gs = GaussianNB()
gs.fit(X,y)
test = [['4.3','3.0','1.1','0.1']]
results = gs.predit(test)
print(results)