前言
本次我们将梳理下朴素贝叶斯(Naive Bayes)的相关内容。
本文约1.6k字,预计阅读10分钟。
概要
朴素贝叶斯算法是一种适用于二分类和多分类分类问题的「分类算法」。在贝叶斯概率框架下,通过相应推导得知,「期望风险最小化等价于后验概率最大化」。对于后验概率的计算,可以通过「联合概率分布 建模」,得到后验概率 (「生成模型」);
对于生成模型来说,根据「贝叶斯定理」,可以将其写成:
在朴素贝叶斯中,由于条件概率 难以计算,因此提出一个强烈的假设:「特征独立性假设」,即各个特征是独立同分布的,不存在交互,这也是朴素贝叶斯名称的来由。先验概率和条件概率的估计不作展开,感兴趣的可以参考《统计学习方法》,通过转化,最终最大化后验概率(MAP),即「先验概率与类条件概率的乘积」:
【注】期望风险最小化等价于后验概率最大化的推导可以参考《机器学习》,详细的推导,可以参考《统计学习方法》。
算法面试
在算法面试中,设计朴素贝叶斯相关的问题包括:
为什么朴素贝叶斯如此“朴素”?
朴素贝叶斯基本原理和预测过程;
简单说说贝叶斯定理;
使用朴素贝叶斯如何进行垃圾分类?
今天我们讨论的问题是:
❝朴素贝叶斯的算法实现。
❞
对于朴素贝叶斯来说,这既对我们的算法原理进行考察,也检验了编程能力。我以建立整个朴素贝叶斯算法模型类来展开,主要分为:
确定朴素贝叶斯的类型(高斯朴素贝叶斯或者伯努利朴素贝叶斯等);
模型的拟合,重点在于模型到底保存了什么内容;
后验概率的计算;
最大后验概率的输出;
1. 模型类型
对于类条件概率参数的估计,我们采用极大似然估计法,首先最重要的是「假设随便变量(特征)服从什么分布」,对于不同的假设,也对应着不同的朴素贝叶斯,例如伯努利朴素贝叶斯、高斯朴素贝叶斯、多项分布朴素贝叶斯。最常见的是通过假设「高斯分布」,在模型拟合中,「只需要估计训练数据(每个类别的所有样本的每个特征)的平均值和标准偏差」。
因此,我们可以得到初步的框架:
class Gaussian_NaiveBayes:
def init(self):
def mean(self, 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)-1))
2. 模型拟合
通过对朴素贝叶斯原理的理解,我们知道,学习联合概率模型,需要通过极大似然法估计先验概率(假设服从伯努利分布)和类条件概率参数,对于高斯朴素贝叶斯来说,整个训练数据集,我们需要保存:
每个类对应的数量(可以计算先验概率)和总样本数量(可以作为模型的一个属性);
每个类的每个特征的均值与标准偏差(可以计算类条件概率);
综上所述,我们可以通过「字典」的形式进行保存:
因此:
def summarize(self, train_data):
summaries = [(self.mean(column), self.stdev(column), len(column)) for column in zip(*train_data)]
return summaries
def fit(self, X, y):
self.total_rows = len(X)
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()}
3. 后验概率的计算
对于每个类别的后验概率计算,需要求得先验概率和类条件概率。首先对于类条件概率,根据高斯公式求得,
def gaussian_probabality(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
然后迭代计算所有类的后验概率:
def calculate_probabalities(self, input_data):
probalalities = {}
for label, summaries in self.model.items():
probalalities[label] = summaries[0][2] / self.total_rows # 先验
for i in range(len(summaries)):
mean, stdev, _ = summaries[i]
probalalities[label] *= self.gaussian_probabality( # 先验 * 条件概率
input_data[i], mean, stdev)
return probalalities
4. 最大后验概率
最大后验概率的计算就是排序,得到最大概率对应的标签值。对于测试集来说,遍历所有样本进行计算。
def predict(self, X_test):
labels = []
for i in X_test:
label = sorted(
self.calculate_probabalities(i).items(),
key=lambda x: x[-1])[-1][0]
labels.append(label)
return np.array(labels)
总结
以上便是对“朴素贝叶斯算法实现”的总结。最重要的是需要一个完善的类框架,才能够好的结合原理进行代码的复现。至于其他几个问题,比较简单,这里就不作详细讨论。
往期精彩回顾
适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑
本站知识星球“黄博的机器学习圈子”(92416895)
本站qq群704220115。
加入微信群请扫码: