1、朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法,对于给定的训练数据集,首先基于特征条件独立假设学习输入/输出的联合概率分布;然后基于此模型,对给定的输入x,利用贝叶斯定理求出后验概率最大的输出y。该方法的实现比较简单,学习和预测的概率都很高,是一种常用的方法。
2、基本方法:设输入空间χ⊆Rn为n维向量的集合,输出空间为类标记集合γ={c_1,c_2,…,c_k}。输入为特征向量x∈χ,输出为类标记y∈γ,X为定义在输入空间χ上的随机向量,Y为定义在输出空间γ上的随机变量。训练数据集T={(x_1,y_1),(x_2,y_2),…,(x_N,y_N)}由P(X,Y)独立同分布产生。
朴素贝叶斯法通过训练数据集学习联合概率分布P(X,Y),对条件概率分布作了条件独立性假设。
先验概率分布为
条件概率分布为
条件概率分布P(X=x|Y=c_k)有指数级数量的参数,其估计实际上是不可行的,事实上,假设x(j)可取值有S_j个,j=1,2,…,n,Y可取值有K个,那么参数个数为K∏S_j。
条件独立性假设为
朴素贝叶斯法实际上学习到的是生成数据机制,属于生成模型,条件独立性假设等于是说用于分类的特征在类确定的条件下都是条件独立的,这种假设会使得朴素贝叶斯变得简单,但有时会牺牲一定的分类准确率。
3、朴素贝叶斯法分类时,对给定的输入x,通过学习到的模型计算后验概率分布,并将后验概率最大的类作为x的类输出。
后验概率的计算根据贝叶斯定理进行:
根据条件独立性假设又有
这也是朴素贝叶斯分类的基本公式。
将朴素贝叶斯分类器表示为:
又分母对所有c_k而言都是相同的,所以,
4、后验概率最大化的含义:朴素贝叶斯法将实例分到后验概率最大的类中,这等价于期望风险最小化,假设0-1损失函数,其中f(X)是分类决策函数:
期望风险函数为下式,期望是对联合分布取的
由此取条件期望为
为了使期望风险最小化,只需对X=x逐个极小化:
根据期望风险最小化准则得到后验概率最大化准则,即朴素贝叶斯法的原理:
5、极大似然估计:朴素贝叶斯法中的学习意味着估计P(Y=c_k)和P(X(j)=x(j)|Y=c_k),应用极大似然估计法估计相应的概率,先验概率P(Y=c_k)的极大似然估计是
设第j个特征x(j)可能的取值集合为{a_j1,a_j2,…,a_jSj},条件概率P(X(j)=a_jl|Y=c_k)的极大似然估计是
其中,j=1,2,…,n;l=1,2,…,S_j;k=1,2,…,K,x_j(j)是第i个样本的第j个特征,a_jl是第j个特征可能取的第l个值,I是指示函数。
6、朴素贝叶斯算法:
- 输入——训练数据T={(x_1,y_1),(x_2,y_2),…,(x_N,y_N)},其中x_i =(x_i(1),x_i(2),… ,x_i(i))T,x_i(i)是第i个样本的第j个特征,x_i(i)∈{a_j1,a_j2,…,a_jSj},a_jl是第j个特征可能取的第l个值;实例x;j=1,2,…,n,l=1,2,…,S_j,y_i∈{c_1,c_2,…,c_K}
- 输出——实例x的分类
- 步骤——
(1) 计算先验概率及条件概率
(2)对于给定的实例x,计算
(3)确定实例x的类别
7、贝叶斯估计:用极大似然估计可能会出现所要估计的概率值为0的情况,这会影响后验概率的计算结果,使分类结果产生偏差,解决该问题的方法是采用贝叶斯估计。
式中λ≥0,等价于在随机变量各个取值的频数上赋予一个正数λ>0,当λ=0时就是极大似然估计,常取λ=1,这时成为拉普拉斯平滑。
同样,先验概率的贝叶斯估计是
【算法实现】
# 高斯朴素贝叶斯
# -*- coding: utf-8 -*-
import numpy as np
from sklearn.naive_bayes import GaussianNB
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
Y = np.array([1, 1, 1, 2, 2, 2])
clf = GaussianNB()
clf.fit(X, Y)
pre = clf.predict(X)
print("数据集预测结果:", pre)
print(clf.predict([[-0.8, -1]]))
clf_pf = GaussianNB()
clf_pf.partial_fit(X, Y, np.unique(Y)) #增加一部分样本
print(clf_pf.predict([[-0.8, -1]]))
# 分析MNIST数据集
import pandas as pd
import numpy as np
import cv2
import random
import time
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 二值化
def binaryzation(img):
cv_img = img.astype(np.uint8)
cv2.threshold(cv_img, 50, 1, cv2.THRESH_BINARY_INV, cv_img)
return cv_img
def Train(trainset, train_labels):
prior_probability = np.zeros(class_num) # 预设先验概率 p(y = j)
conditional_probability = np.zeros((class_num, feature_len, 2)) # 预设条件概率 p(xk | y)
# 计算先验概率及条件概率
for i in range(len(train_labels)): # 训练集标签的数量
img = binaryzation(trainset[i]) # 图片二值化 对每一个图片进行二值化
label = train_labels[i] # 对每一张图片赋予标签
prior_probability[label] += 1 # 先验概率,总要计算出训练集中同一种标签的数量,比如说是数字1的图片有多少张
for j in range(feature_len): # 对每一张图片的每一个像素进行操作,统计同一种标签下的图像中各像素取值的数量
conditional_probability[label][j][img[j]] += 1 # 属于第i类的图像中像素j为0和1的数量
prior_probability = np.log((prior_probability + 1) / (len(trainset))) # 先验概率平滑
# 将概率归到[1,10000]
for i in range(class_num):
for j in range(feature_len):
# 经过二值化后图像只有0,1两种取值
pix_0 = conditional_probability[i][j][0] # 得到属于第i类的图像中第j个像素像素值为0的数量
pix_1 = conditional_probability[i][j][1] # 得到属于第i类的图像中第j个像素像素值为1的数量
# 计算0,1像素点对应的条件概率 后验概率平滑
probalility_0 = (float(pix_0) + 1) / (float(pix_0 + pix_1) + 2) * 1000000 # 拉普拉斯平滑
probalility_1 = (float(pix_1) + 1) / (float(pix_0 + pix_1) + 2) * 1000000
conditional_probability[i][j][0] = np.log(probalility_0) # 得到 P(Xk|y)
conditional_probability[i][j][1] = np.log(probalility_1)
return prior_probability, conditional_probability
# 计算概率
def calculate_probability(img, label):
probability = prior_probability[label] # 先验概率
sum = 0
for i in range(len(img)): # 取log变为相加
sum += int(conditional_probability[label][i][img[i]])
probability = probability + sum
return probability
def Predict(testset, prior_probability, conditional_probability):
predict = []
for img in testset:
# 图像二值化
img = binaryzation(img)
max_label = 0
max_probability = calculate_probability(img, 0)
for j in range(1, 10):
probability = calculate_probability(img, j)
if max_probability < probability:
max_label = j
max_probability = probability
predict.append(max_label)
return np.array(predict)
class_num = 10
feature_len = 784
if __name__ == '__main__':
print('Start read data')
time_1 = time.time()
raw_data = pd.read_csv('./mnistdata/mnist_train.csv', header=0)
data = raw_data.values
imgs = data[0::, 1::] # 取出像素值
labels = data[::, 0] # 取出标签值
time_2 = time.time()
print('read data cost ', time_2 - time_1, ' second', '\n')
print('Start training')
prior_probability, conditional_probability = Train(imgs, labels)
time_3 = time.time()
print('training cost ', time_3 - time_2, ' second', '\n')
test_data = pd.read_csv('./mnistdata/mnist_test.csv', header=0)
test_data = test_data.values
test_imgs = test_data[0::, 1::] # 取出测试集像素值
test_labels = test_data[::, 0] # 取出测试集标签值
print('Start predicting')
test_predict = Predict(test_imgs, prior_probability, conditional_probability)
time_4 = time.time()
print('predicting cost ', time_4 - time_3, ' second', '\n')
score = accuracy_score(test_labels, test_predict)
print("The accruacy socre is ", score)