1.前言
朴素贝叶斯的原理比较简单,在这我简单的推导一下公式的由来。
假设我们的X有五个特征分别为x1,x2,x3,x4,x5。则有
在朴素贝叶斯算法中,它假设了这五个变量之间是相互独立的:
则上式可化简为:
而我们需要计算的概率根据贝叶斯公式则可化简为:
这就是我们需要计算的概率,这里我们使用高斯模型去拟合
这里我推荐一下吴恩达老师的课程方便大家了解朴素贝叶斯:
2.源码讲解
注意我这里实现的是朴素贝叶斯模型,而不是高斯判别模型!!!ss
2.1 def fit():
def fit(self, X, y):
self.X = X
self.y = y
self.classes = np.unique(y)
self.parameters = {}
for i, c in enumerate(self.classes):
# 计算每个种类的平均值,方差,先验概率
X_Index_c = X[np.where(y == c)]
X_index_c_mean = np.mean(X_Index_c, axis=0, keepdims=True)
X_index_c_var = np.var(X_Index_c, axis=0, keepdims=True)
parameters = {"mean": X_index_c_mean, "var": X_index_c_var, "prior": X_Index_c.shape[0] / X.shape[0]}
self.parameters["class" + str(c)] = parameters
fit()函数计算每个特征x1,x2...xn的方差与平均值,以此后面来估算P(xi|y)
2.2 def _pdf:
def _pdf(self, X, classes):
# 一维高斯分布的概率密度函数
# eps为防止分母为0
eps = 1e-4
mean = self.parameters["class" + str(classes)]["mean"]
var = self.parameters["class" + str(classes)]["var"]
# 取对数防止数值溢出
# numerator.shape = [m_sample,feature]
numerator = np.exp(-(X - mean) ** 2 / (2 * var + eps))
denominator = np.sqrt(2 * np.pi * var + eps)
# 朴素贝叶斯假设(每个特征之间相互独立)
# P(x1,x2,x3|Y) = P(x1|Y)*P(x2|Y)*P(x3|Y),取对数相乘变为相加
# result.shape = [m_sample,1]
result = np.sum(np.log(numerator / denominator), axis=1, keepdims=True)
return result.T
这个函数主要是计算P(X|y) = P(x1|y) * P(x2|y) *... P(xn|y)
其中
这里的对数运算是防止数值溢出
2.3 def _predict
def _predict(self, X):
# 计算每个种类的概率P(Y|x1,x2,x3) = P(Y)*P(x1|Y)*P(x2|Y)*P(x3|Y)
output = []
for y in range(self.classes.shape[0]):
prior = np.log(self.parameters["class" + str(y)]["prior"])
posterior = self._pdf(X, y)
prediction = prior + posterior
output.append(prediction)
return output
_pdf()函数已计算出了P(X|y),_predict()函数计算P(y|X)=P(X|y) * P(y)
2.4 def predicit
def predict(self, X):
# 取概率最大的类别返回预测值
output = self._predict(X)
output = np.reshape(output, (self.classes.shape[0], X.shape[0]))
prediction = np.argmax(output, axis=0)
return prediction
返回概率最大的种类为预测值
3.源码地址
项目包括了许多机器学习算法的简洁实现
此文章为记录自己一路的学习路程,也希望能给广大初学者们一点点帮助,如有错误,疑惑欢迎一起交流。