朴素贝叶斯
朴素贝叶斯
文章目录
- 朴素贝叶斯
- 朴素贝叶斯算法概念
- 贝叶斯方法
- 朴素贝叶斯
- 条件概率
- 全概率公式
- 贝叶斯定理
- 为什么“朴素”
- 典型用例——邮件分类
- 贝叶斯定理基础公式
- 特征条件独立假设下的似然函数展开
- 类先验概率计算
- 后验概率计算(省略归一化因子)
- 垃圾邮件分类示例中的具体计算
- 类先验概率
- 条件概率
- 后验概率比较
- 分类决策规则
- 代码实现
- 使用numpy
- 使用Sklern
朴素贝叶斯算法概念
贝叶斯方法
贝叶斯方法是以贝叶斯原理为基础,使用概率统计的知识对样本数据集进行分类。由于其有着坚实的数学基础,贝叶斯分类算法的误判率是很低的。贝叶斯方法的特点是结合先验概率和后验概率,即避免了只使用先验概率的主观偏见,也避免了单独使用样本信息的过拟合现象。贝叶斯分类算法在数据集较大的情况下表现出较高的准确率,同时算法本身也比较简单。
朴素贝叶斯
朴素贝叶斯算法(Naive Bayesian algorithm) 是应用最为广泛的分类算法之一。
朴素贝叶斯方法是在贝叶斯算法的基础上进行了相应的简化,即假定给定目标值时属性之间相互条件独立。也就是说没有哪个属性变量对于决策结果来说占有着较大的比重,也没有哪个属性变量对于决策结果占有着较小的比重。虽然这个简化方式在一定程度上降低了贝叶斯分类算法的分类效果,但是在实际的应用场景中,极大地简化了贝叶斯方法的复杂性。
条件概率
条件分布试图回答这样一个问题,当我们知道 X X X必须取某个值 x x x时, Y Y Y上的概率分布是什么?在离散情况下,给定 Y Y Y的条件概率质量函数是简单的:
p Y ∣ X ( y ∣ x ) = p X Y ( x , y ) p X ( x ) p_{Y | X}(y | x)=\frac{p_{X Y}(x, y)}{p_{X}(x)} pY∣X(y∣x)=pX(x)pXY(x,y)
假设分母不等于0。
在连续的情况下,在技术上要复杂一点,因为连续随机变量的概率等于零。忽略这一技术点,我们通过类比离散情况,简单地定义给定 X = x X = x X=x的条件概率密度为:
f Y ∣ X ( y ∣ x ) = f X Y ( x , y ) f X ( x ) f_{Y | X}(y | x)=\frac{f_{X Y}(x, y)}{f_{X}(x)} fY∣X(y∣x)=fX(x)fXY(x,y)
假设分母不等于0。
全概率公式
全概率公式是概率论中的重要工具,用于将复杂事件的概率分解为多个简单事件概率的组合,从而简化计算。它的核心思想是 “分而治之”,通过将样本空间划分为若干互斥且完备的事件组,间接求出目标事件的概率。
P ( A ) = ∑ i = 1 n P ( B i ) ⋅ P ( A ∣ B i ) P(A) = \sum\limits_{i=1}^n P(B_i) \cdot P(A|B_i) P(A)=i=1∑nP(Bi)⋅P(A∣Bi)
贝叶斯定理
贝叶斯理论认为任意未知量θ都可以看作一个随机变量,对该未知量的描述可以用一个概率分布π(θ)来概括,这是贝叶斯学派最基本的观点。当这个概率分布在进行现场试验或者抽样前就已确定,便可将该分布称为先验分布,再结合由给定数据集X计算样本的似然函数L(θ|**X)**后,即可应用贝叶斯公式计算该未知量的后验概率分布。
P ( c ∣ x ) = P ( x ∣ c ) P ( c ) 似然函数 类先验概率 ∑ P ( x ∣ c ) P ( c ) 全概率 P(c|x)=\frac{\overset{\text{似然函数 } \text{ 类先验概率}}{P(x|c)P(c)}}{\underset{\text{全概率}}{\sum P(x|c)P(c)}} P(c∣x)=全概率∑P(x∣c)P(c)P(x∣c)P(c)似然函数 类先验概率
为什么“朴素”
“朴素” 体现在朴素贝叶斯算法假定特征条件之间相互独立。在现实世界中,很多特征之间往往存在关联,但朴素贝叶斯为简化计算和模型构建,做出了这一相对 “简单粗暴” 的假设 。
这是朴素贝叶斯 “朴素” 之处。假设在给定类别 c 的条件下,各个特征x1,x2,x3,…,xn之间相互独立。基于此假设,(P(x|c)) 可展开为:
P ( x ∣ c ) = P ( x 1 ∣ c ) P ( x 2 ∣ c ) ⋯ P ( x n ∣ c ) P(x|c) = P(x_1|c)P(x_2|c)\cdots P(x_n|c) P(x∣c)=P(x1∣c)P(x2∣c)⋯P(xn∣c)
比如在文本分类中,假设每个词的出现都不依赖于其他词(实际不完全如此,但该假设简化计算)。
基于此假设,在计算给定类别下特征出现的联合概率时,可将其转化为各个特征条件概率的乘积,大幅降低计算复杂度。例如在文本分类里,正常情况下词语间存在语义关联、语法搭配等关系,但朴素贝叶斯假设每个词的出现都不依赖于其他词,从而简化模型,使其在很多场景下仍能有效工作。 正是因为这种对特征独立性的简化假设,该算法被称为 “朴素” 的贝叶斯算法。
典型用例——邮件分类
贝叶斯定理基础公式
P ( c ∣ x ) = P ( x ∣ c ) P ( c ) P ( x ) P(c|x) = \frac{P(x|c)P(c)}{P(x)} P(c∣x)=P(x)P(x∣c)P(c)
特征条件独立假设下的似然函数展开
P ( x ∣ c ) = P ( x 1 ∣ c ) P ( x 2 ∣ c ) ⋯ P ( x n ∣ c ) P(x|c) = P(x_1|c)P(x_2|c)\cdots P(x_n|c) P(x∣c)=P(x1∣c)P(x2∣c)⋯P(xn∣c)
类先验概率计算
P ( c ) = N c N P(c)=\frac{N_c}{N} P(c)=NNc
后验概率计算(省略归一化因子)
P ( c ∣ x ) ∝ P ( c ) ∏ i = 1 n P ( x i ∣ c ) P(c|x) \propto P(c)\prod_{i = 1}^{n}P(x_i|c) P(c∣x)∝P(c)i=1∏nP(xi∣c)
垃圾邮件分类示例中的具体计算
类先验概率
P ( c 1 ) = 0.3 , P ( c 2 ) = 0.7 P(c_1) = 0.3, \quad P(c_2) = 0.7 P(c1)=0.3,P(c2)=0.7
条件概率
- 垃圾邮件中出现“促销”的概率: P ( x 1 ∣ c 1 ) P(x_1|c_1) P(x1∣c1)
- 正常邮件中出现“促销”的概率: P ( x 1 ∣ c 2 ) P(x_1|c_2) P(x1∣c2)
- 垃圾邮件中未出现“免费”的概率: P ( ¬ x 2 ∣ c 1 ) P(\neg x_2|c_1) P(¬x2∣c1)
- 正常邮件中未出现“免费”的概率: P ( ¬ x 2 ∣ c 2 ) P(\neg x_2|c_2) P(¬x2∣c2)
后验概率比较
P ( c 1 ∣ x ) ∝ P ( c 1 ) ⋅ P ( x 1 ∣ c 1 ) ⋅ P ( ¬ x 2 ∣ c 1 ) P(c_1|x) \propto P(c_1) \cdot P(x_1|c_1) \cdot P(\neg x_2|c_1) P(c1∣x)∝P(c1)⋅P(x1∣c1)⋅P(¬x2∣c1)
P ( c 2 ∣ x ) ∝ P ( c 2 ) ⋅ P ( x 1 ∣ c 2 ) ⋅ P ( ¬ x 2 ∣ c 2 ) P(c_2|x) \propto P(c_2) \cdot P(x_1|c_2) \cdot P(\neg x_2|c_2) P(c2∣x)∝P(c2)⋅P(x1∣c2)⋅P(¬x2∣c2)
分类决策规则
c ^ = arg max c ∈ { c 1 , c 2 } P ( c ∣ x ) \hat{c} = \arg\max_{c \in \{c_1, c_2\}} P(c|x) c^=argc∈{c1,c2}maxP(c∣x)
代码实现
使用numpy
# 使用numpy实现朴素贝叶斯
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt### 构造数据集
### 来自于李航统计学习方法表4.1
x1 = [1,1,1,1,1,2,2,2,2,2,3,3,3,3,3]
x2 = ['S','M','M','S','S','S','M','M','L','L','L','M','M','L','L']
y = [-1,-1,1,1,-1,-1,-1,1,1,1,1,1,1,1,-1]df = pd.DataFrame({'x1':x1, 'x2':x2, 'y':y})X = df[['x1','x2']]
y = df[['y']]
y[y.columns[0]].unique()def nb_fit(X, y):# 获取所有类别标签classes = y[y.columns[0]].unique()print(classes)# 计算每个类别的样本数量class_count = y[y.columns[0]].value_counts()# 计算每个类别的先验概率(类别概率)class_prior = class_count/len(y)# 初始化条件概率字典prior = dict()# 遍历每个特征列for col in X.columns:# 遍历每个类别for j in classes:# 获取当前类别下该特征列的值统计p_x_y = X[(y==j).values][col].value_counts()# 遍历该特征列的所有可能取值for i in p_x_y.index:# 计算条件概率 P(X_i|Y_j)# 即:在类别j下,特征col取值为i的概率prior[(col, i, j)] = p_x_y[i]/class_count[j]# 返回:类别列表、类别先验概率、条件概率字典return classes, class_prior, priorclasses, class_prior, prior = nb_fit(X, y)def predict(X_test):res = []for c in classes:p_y = class_prior[c]p_x_y = 1for i in X_test.items():p_x_y *= prior[tuple(list(i)+[c])]res.append(p_y*p_x_y)return classes[np.argmax(res)]X_test = {'x1': 2, 'x2': 'S'}
print('测试数据预测类别为:', predict(X_test))
使用Sklern
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0)
gnb = GaussianNB()
y_pred = gnb.fit(X_train, y_train).predict(X_test)
print("Accuracy of GaussianNB in iris data test:", accuracy_score(y_test, y_pred))