朴素贝叶斯分类器
朴素贝叶斯介绍
贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。
1.常见概率的计算
以以下数据集为例
def data_set():
#第一列是车型(轿车|皮卡|SUV),
#第二行是婚姻状态(1已婚|2单身|3离婚),
#第三列是是否有贷款(0无|1有),
#第四列是是否已有车(0无|1有),
#第五列为是否买车(0n|1y)
dataset = [
'''1'''["轿车", "已婚", "无贷款", "无车", "不买"],
'''2'''["轿车", "已婚", "无贷款", "有车", "不买"],
'''3'''["皮卡", "单身", "无贷款", "无车", "买"],
'''4'''["SUV", "离婚", "有贷款", "无车", "买"],
'''5'''["SUV", "已婚", "无贷款", "有车", "买"],
'''6'''["皮卡", "单身", "有贷款", "无车", "买"],
'''7'''["轿车", "单身", "无贷款", "无车", "不买"],
'''8'''["轿车", "离婚", "有贷款", "无车", "买"],
'''9'''["皮卡", "离婚", "有贷款", "有车", "不买"],
'''10'''["轿车", "单身", "有贷款", "有车", "买"],
'''11'''["SUV", "单身", "无贷款", "有车", "买"],
'''12'''["SUV", "离婚", "有贷款", "有车", "买"],
'''13'''["皮卡", "已婚", "无贷款", "有车", "不买"]
]
labels = [row[-1] for row in dataset]
return dataset,labels
(1)概率公式
条件概率:表示事件a在另一个事件B已经发生条件下的发生概率,记为P(A|B)
e.g. 在买车的条件下,是单身的概率为
1.在买车条件下,有3,4,5,6,8,10,11,12,共8个样本
2.在8个样本中,有3,6,10,11,共4个单身的样本
3.则P(单身|买车) = 4/8 = 0.5
联合概率:表示多个条件同时处理的概率, P ( A B ) = P ( A ) P ( B ∣ A ) P(AB) = P(A)P(B|A) P(AB)=P(A)P(B∣A)
特征条件独立: P ( A B ) = P ( A ) P ( B ) P(AB) = P(A)P(B) P(AB)=P(A)P(B)
1.情感状况是单身的有3,6,7,10,11,共5个样本概率为5/13
2.在单身中,无贷款的有3,7,11,共三个样本,概率为3/5
3.则既单身又体型匀称的概率为5/13 * 3/5 = 3/13
联合概率和条件概率
在买车的情况下,情感状况单身,且无贷款的概率为 P ( A B ∣ C ) = P ( A ∣ C ) P ( B ∣ A C ) P(AB|C) = P(A|C)P(B|AC) P(AB∣C)=P(A∣C)P(B∣AC)
1.在买车条件下,有3,4,5,6,8,10,11,12,共8个样本
2.在这8个样本中,单身的有3,6,10,11,共4个样本,概率为4/8 = 0.5
3.在这4个样本中,无贷款的有3,11,共2个样本,概率为2/4 = 0.5
则P(单身,无贷款|买车) = 0.5 * 0.5 = 0.25
2.贝叶斯公式
P ( C ∣ W ) = P ( W ∣ C ) P ( C ) P ( W ) P(C|W) = \frac{P(W|C)P(C)}{P(W)} P(C∣W)=P(W)P(W∣C)P(C)
1.P©表示C出现的概率
2.P(W|C)表示C条件下W出现的概率
3.P(W)表示W出现的概率
3.朴素贝叶斯
朴素贝叶斯可理解为在贝叶斯基础上增加:特征条件独立,即特征之间是互为独立的 P ( X ∣ Y ) = P ( X 1 ∣ Y ) P ( X 2 ∣ Y ) . . . . . . P ( X n ∣ Y ) P(X|Y) = P(X_1 |Y)P(X_2|Y)......P(X_n|Y) P(X∣Y)=P(X1∣Y)P(X2∣Y)......P(Xn∣Y)
根据以上公式可得出我们需要计算出各个特征的先验概率以及似然概率,然后相乘后选择概率较大的,即可得到答案,
1.先验概率P(X)
首先统计出买或不买的个数,然后除以整个测试集长度
def calculate_prior(dataset):
# 计算先验概率
prior = {}
for label in dataset:#先统计0,1出现的个数
prior[label[-1]] = prior.get(label[-1],0) + 1
total = len(dataset)
for k in prior:#除长度得到先验概率
prior[k] = prior[k]/total
return prior
测试
2. 似然概率P(Y|X)
计算每个特征分别在买和不买中的个数,再除以对应买或不买的总个数
def calculate_likelihood(dataset):#计算似然概率
likelihood = {}
# 遍历每个类别
for category in set([label[-1] for label in dataset]):
# 初始化类别的计数器
total_count = 0
# 初始化类别的特征值计数器
feature_counts = {}
# 计算每个类别下每个特征值的计数
for features in dataset:
if features[-1] == category:
total_count += 1
for i, feature_value in enumerate(features[:-1]): # 前四个元素特征
feature_counts.setdefault(i, {}) # 初始化特征索引的字典,i代表下标
feature_counts[i][feature_value] = feature_counts[i].get(feature_value, 0) + 1#计算出现的次数
# 计算似然概率
for i, feature_value_counts in feature_counts.items():
for feature_value, count in feature_value_counts.items():
likelihood[(category, feature_value)] = count / total_count
return likelihood
得到结果为
3.后验概率P(X|Y)
def calculate_posterior(prior, likelihood, test_set):#计算后验概率
posterior = {}
for category in prior:
posterior[category] = prior[category]#后验概率初始化为先验概率
for feature_index,feature_value in enumerate(test_set):#取测试的下标和属性
posterior[category] *= likelihood.get((category,feature_value))
return posterior
结果
4.结果输出
用以下函数返回判断结果
def return_result(posterior):
return ('买' if posterior['买'] > posterior['不买'] else '不买')
以下为测试样例
if __name__ == "__main__":
dataset,labels = data_set()
prior = calculate_prior(dataset)
likelihood = calculate_likelihood(dataset)
test_set = ["轿车", "离婚", "无贷款", "有车"]
posterior = calculate_posterior(prior, likelihood, test_set)
print(posterior)
print(return_result(posterior))
4.总结
优点:
1.逻辑简单,易于实现
2.空间开销小
缺点:
朴素贝叶斯和其他分类方法相比具有较小误差,其实不是,这是因为朴素贝叶斯简单的把属性之间假设为相互独立,这种假设在现实生活中往往是不可取的,如果属性之间相关性较强,则分类效果不会很好