朴素贝叶斯
朴素贝叶斯直接找出特征输出Y和特征X的联合分布P(X,Y),然后用P(Y|X)=P(X,Y)/P(X)得出,贝叶斯学派的思想可以概括为先验概率+数据=后验概率,由于贝叶斯诞生的时候,频率学派是主流,所以贝叶斯学派的思想一直受到质疑,首先是先验概率,一般来说先验概率就是我们对于数据所在领域的历史经验,但是经验这个东西很难被量化,于是贝叶斯学派开始进行假设分布,比如正态分布,beta分布等,但是这只是假设,一般没有特定的依据,所以一直被频率学派认为这是很荒谬的事情。回到现在,贝叶斯理论在分本分类的领域中还是很好用的。
首先来看条件独立公式,假设X和Y相互独立,则联合分布概率为P(X,Y),条件概率指的是一个随机变量,在另一随机变量取值已知的情况下,取某一个值的概率,P(X|Y)=P(X,Y)/P(Y),再看全概率公式
有了这些公式我们就可以推出贝叶斯公式
最大似然法推导
假设我们现在有m个样本 每个样本有n个特征,输出有K个类别,从样本我们可以得到先验分布,还可以得到条件分布概率,就可以利用贝叶斯公式得到X,Y的联合分布P(X,Y)了,先验概率和条件概率的极大似然估计很容易推出,也是第四章的课后习题,步骤如下
(这两幅图最后一步都有笔误,不是P应该是I,我们要求的是每个标签的个数比上总样本数)
朴素贝叶斯在这里做了一个很大胆的假设,他假设X的n个维度相互独立,所以就有了这一步大大的简化了这个条件分布的复杂性,但是同样的可能会给预测带来不准确性,这也是朴素贝叶斯算法一个缺点,针对样本特征之间不独立的数据集没有很好的效果,那么如何判定新来的样本特征是属于哪个类型的呢?就用后验概率最大化来判断分类,找出最大的条件概率所对应的类别,就是朴素贝叶斯的预测
贝叶斯估计
这主要是针对某些时候,可能某些类别在样嫩种没有出现,这样可能导致P(X|Y)为0,影响后验的估计,为了解决,引入了拉普拉斯平滑,此时得到了书上的4.10和4.11公式,推导过程如下,也是课后习题要求的推导过程
朴素贝叶斯的流程和公式推导如上,具体例子可以根据书上给出的两个例子自己去动手试一试,下面是朴素贝叶斯的代码实现,用的是极大似然估计,贝叶斯估计的代码将在后续学明白贝叶斯估计的时候再贴上
在scikit learn中的朴素贝叶斯有三种(四种) 分别是高斯分布的朴素贝叶斯,多项式分布的朴素贝叶斯和伯努利分布的朴素贝叶斯,还有一种叫做补集贝叶斯,针对了样本特征分布分别是正态分布(连续值),多元离散值,用多项式分布,二元离散值或者很稀疏的多元离散值,用伯努利分布,具体案例具体分析再决定
import pandas as pd
import numpy as np
from sklearn.datasets import load_digits
digits = load_digits()
digits
digits.data
set(digits.target)
train=digits.data
labels=digits.target
class NaiveBayes(object):
def getTrainSet(dataSet):
dataSet_1 = np.array(dataSet)
trainData = dataSet_1[:,0:dataSet_1.shape[1]-1]
labels = dataSet_1[:,dataSet_1.shape[1]-1]
return trainData, labels
def classify(self, trainData, labels, features):
labels = list(labels)
labelset = set(labels)
P_y = {}
for label in labelset:
P_y[label] = labels.count(label)/float(len(labels))
print(label,P_y[label])
P_xy = {}
for y in P_y.keys():
y_index = [i for i, label in enumerate(labels) if label == y]
for j in range(len(features)):
x_index = [i for i, feature in enumerate(trainData[:,j]) if feature == features[j]]
xy_count = len(set(x_index) & set(y_index))
pkey = str(features[j]) + '*' + str(y)
P_xy[pkey] = xy_count / float(len(labels))
print(pkey,P_xy[pkey])
P = {}
for y in P_y.keys():
for x in features:
pkey = str(x) + '|' + str(y)
P[pkey] = P_xy[str(x)+'*'+str(y)] / float(P_y[y])
print(pkey,P[pkey])
F = {}
for y in P_y:
F[y] = P_y[y]
for x in features:
F[y] = F[y]*P[str(x)+'|'+str(y)]
print(str(x),str(y),F[y])
features_label = max(F, key=F.get)
return features_label