本章要点:
前言
- 朴素贝叶斯是生成模型,学习联合概率分布。NB(Naive Bayesian )是典型的生成模型,与之对应的是判别模型,如逻辑回归。
- 给定数据集的时候,我们能知道不同类别的分布,这个很好统计的量叫先验概率p(Y=ck)
- 垃圾邮件识别可以用朴素贝叶斯的方法。
1,朴素贝叶斯法
朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。
- 贝叶斯定理
- 特征条件独立假设
1.1 贝叶斯定理
- 先验概率分布:P(Y=ck),k=1,2,…,K
- 条件概率分布:P(X=x∣Y=ck)=P(X(1)=x(1),…,X(n)=x(n)∣Y=ck),k=1,2,…,K
参数数量:
条件概率分布P(X=x∣Y=ck)有指数级数数量的参数,其实际估计是不可行的。
因此引入条件独立假设。
1.2 条件独立假设
Independent and identically distributed
求P(Y∣X),其中X∈{X1,X2,…,Xn},条件独立假设这里给定Y的情况下:
- 每一个Xi和其他的每个Xk是条件独立的
- 每一个Xi和其他的每个Xk的子集是条件独立的
条件独立假设是:
也就是:
条件独立假设等于是说用于分类的特征在类确定的条件下都是条件独立的。
由1.1和1.2化简后可得,朴素贝叶斯分类器克表示为:
2,朴素贝叶斯法的参数估计
- 极大似然估计
- 贝叶斯估计
2.1 极大似然估计
在朴素贝叶斯法中,学习意味着估计P(Y=ck)和P(X(j)=ajl∣Y=ck)。因此可以应用极大似然估计法估计相应的概率。
先验概率P(Y=ck)的极大似然估计是:
条件概率P(X(j)=ajl∣Y=ck)的极大似然估计是:
2.2 贝叶斯估计
对于x的某个特征的取值没有在先验中出现的情况,如果使用极大似然估计,这种情况可能性就是0。但是出现这种情况的原因通常是因为数据集不能覆盖样本空间,出现未知的情况处理策略就是做平滑。
先验概率:
条件概率:
其中λ≥0
当λ=0的时候,就是极大似然估计。
当λ=1的时候,这个平滑就叫做拉普拉斯平滑(Laplace Smoothing)。相当于给未知变量定了先验概率。
扩展
树增强朴素贝叶斯
IID强限制放宽,就是TAN(Tree Augmented Naive Bayes)。可以看做是NB到贝叶斯网的过渡。
贝叶斯网:
朴素贝叶斯法中假设输入变量都是条件独立的,如果假设他们之间存在概率依存关系,模型就变成了贝叶斯网络。这个书中简单提了一句作为扩展。
3,代码实现
导入数据:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from collections import Counter
import math
# data
def create_data():
iris = load_iris()
df = pd.DataFrame(iris.data, columns = iris.feature_names)
df['label'] = iris.target
df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label']
data = np.array(df.iloc[:100,:])
# print(data)
return data[:,:-1],data[:,-1]
X,y = create_data()
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
3.1 高斯朴素贝叶斯的实现
特征的可能性被假设为高斯
概率密度函数:
数学期望(mean):μ
方差:σ2=N∑(X−μ)2
则,**高斯朴素贝叶斯分类器(GaussianNB)**为:
GaussianNB高斯朴素贝叶斯:
class NaiveBayes:
def __init__(self):
self.model = None
# 数学期望,
@staticmethod
def mean(X):
return sum(X) / float(len(X))
# 标准差(方差),
def stdev(self, X):
avg = self.mean(X)
return math.sqrt(sum([pow(x-avg, 2) for x in X]) / float(len(X)))
# 概率密度函数
def gaussian_probability(self, x, mean, stdev):
exponent = math.exp(-(math.pow(x-mean, 2) /
(2 * math.pow(stdev, 2))))
return (1/ (math.sqrt(2 * math.pi)*stdev)) * exponent
# 处理X_train
def summarize(self, trian_data):
summarizes = [(self.mean(i), self.stdev(i))
for i in zip(*trian_data)]
return summarizes
# 分类别求出数学期望和标准差
def fit(self, X, y):
labels = list(set(y))
data = {label : [] for label in labels}
for f,label in zip(X,y):
data[label].append(f)
self.model = {
label : self.summarize(value)
for label, value in data.items()
}
return 'gaussianNB train done!'
# 计算概率
def calculate_probabilityies(self, input_data):
probabilities = {}
for label, value in self.model.items():
probabilities[label] = 1
for i in range(len(value)):# 求每一个特征下的高斯概率密度函数值,并相乘
mean, stdev = value[i]
probabilities[label] *= self.gaussian_probability(
input_data[i], mean, stdev)
return probabilities
# 类别
def predict(self, X_test):
label = sorted(self.calculate_probabilityies(X_test).items(),
key = lambda x: x[-1])[-1][0]
return label
def score(self, X_test, y_test):
right = 0
for X,y in zip(X_test, y_test):
label = self.predict(X)
if label == y:
right +=1
return right / float(len(X_test))
model = NaiveBayes()
model.fit(X_train,y_train)
print(model.model)
'gaussianNB train done!'
{0.0: [(5.002857142857143, 0.29998639424929574),
(3.388571428571429, 0.3845378885819992),
(1.4657142857142855, 0.1217558614437858),
(0.2485714285714285, 0.11306490821376786)],
1.0: [(5.905714285714287, 0.5376896912547537),
(2.7971428571428567, 0.32992268729482166),
(4.225714285714286, 0.4812738199776905),
(1.3314285714285712, 0.20808161664037853)]}
model.predict([4.4, 3.2, 1.3, 0.2])
0.0
model.score(X_test, y_test)
1.0
3.2 scikit-learn实现
from sklearn.naive_bayes import GaussianNB
clf = GaussianNB()
clf.fit(X_train, y_train)
clf.score(X_test,y_test)
1.0
clf.predict([[4.4, 3.2, 1.3, 0.2]])
array([0.])
from sklearn.naive_bayes import BernoulliNB, MultinomialNB # 伯努利模型和多项式模型
参考:
参考书目:李航《统计学习算法》第二版;
参 考:https://github.com/SmirkCao/Lihang
参 考:https://github.com/fengdu78/lihang-code