机器学习4 朴素贝叶斯

4.1 朴素贝叶斯模型

P ( C ∣ F 1 , F 2 , . . . , F n ) = P ( F 1 , F 2 , . . . , F n ∣ C ) ∗ P ( C ) P ( F 1 , F 2 , . . . , F n ) P(C|F_1,F_2,...,F_n)=\frac{P(F_1,F_2,...,F_n|C)*P(C)}{P(F_1,F_2,...,F_n)} P(CF1,F2,...,Fn)=P(F1,F2,...,Fn)P(F1,F2,...,FnC)P(C)

= P ( F 1 ∣ C ) ∗ P ( F 2 ∣ C ) ∗ . . . ∗ P ( F n ∣ C ) ∗ P ( C ) P ( F 1 , F 2 , . . . , F n ) =\frac{P(F_1|C)*P(F_2|C)*...*P(F_n|C)*P(C)}{P(F_1,F_2,...,F_n)} =P(F1,F2,...,Fn)P(F1C)P(F2C)...P(FnC)P(C)

拉普拉斯平滑系数

P ( F 1 ∣ C ) = n i + a n + a m P(F_1|C)=\frac{n_i+a}{n+am} P(F1C)=n+amni+a

朴素⻉叶斯优缺点:

  1. 优点

a.朴素⻉叶斯模型发源于古典数学理论,有稳定的分类效率;b.对缺失数据不太敏感,算法也比较简;c.常用于文本分类分类准确度高,速度快.

  1. 缺点

a.由于使用了样本属性独立性的假设,所以如果特征属性有关联时其效果不好; b.需要计算先验概率,而先验概率很多时候取决于假设,假设的模型可以有很多种,因此在某些时候会由于假设的先验模型的原因导致预测效果不佳

4.2 模型参数估计

import numpy as np

class BernoulliNavieBayes:

    def __init__(self, alpha=1.):
        self.alpha = alpha # 平滑系数

    def _class_prior_proba_log(self, y, classes):
        '''计算所有类别先验概率P(y=c_k)'''
        c_count = np.count_nonzero(y == classes[:, None], axis=1)  # 统计各类别样本数量c_count =[0:5,1:5]
        p = (c_count + self.alpha) / (len(y) + len(classes) * self.alpha) # 计算各类别先验概率(平滑修正)p[0.5,0.5]
        return np.log(p)

    def _conditional_proba_log(self, X, y, classes):
        '''计算所有条件概率P(x^(j)|y=c_k)的对数'''
        _, n = X.shape     # [10,3]
        cls_num = len(classes)   # k=2

        # P_log: 2个条件概率的对数的矩阵
        # 矩阵P_log[0]存储所有log(P(x^(j)=0|y=c_k))
        # 矩阵P_log[1]存储所有log(P(x^(j)=1|y=c_k))
        P_log = np.empty((2, cls_num, n))  # [2,2,3] 2(是,不是), K(y1,y2,...,yk), n(x1,x2,...,xn)

        # 迭代每一个类别c_k
        for indx, cls in enumerate(classes): # k,c=0,0
            # 获取类别为c_k的实例
            X_c = X[y == cls]
            # 统计各特征值为1的实例的数量
            count1 = np.count_nonzero(X_c, axis=0) # count1=[3,2,1]
            # 计算条件概率P(x^(j)=1|y=c_k)(平滑修正)
            p1 = (count1 + self.alpha) / (len(X_c) + 2 * self.alpha)
            # 将log(P(x^(j)=0|y=c_k))和log(P(x^(j)=1|y=c_k))存入矩阵
            P_log[0, indx] = np.log(1 - p1)
            P_log[1, indx] = np.log(p1)

        return P_log

    def train(self, X_train, y_train):
        '''训练模型'''

        # 获取所有类别
        self.classes = np.unique(y_train)  # classes [0,1]
        # 计算并保存所有先验概率的对数
        self.pp_log = self._class_prior_proba_log(y_train, self.classes)
        # 计算并保存所有条件概率的对数
        self.cp_log = self._conditional_proba_log(X_train, y_train, self.classes)

    def _predict(self, x):
        '''对单个实例进行预测'''

        K = len(self.classes)
        p_log = np.empty(K)

        # 分别获取各特征值为1和0的索引
        idx1 = x == 1
        idx0 = ~idx1

        # 迭代每一个类别c_k
        for k in range(K):
            # 计算后验概率P(c_k|x)分子部分的对数.  x=[1,1,0]
            p_log[k] = self.pp_log[k] + np.sum(self.cp_log[0, k][idx0]) \
                                    + np.sum(self.cp_log[1, k][idx1])

        # 返回具有最大后验概率的类别
        return np.argmax(p_log)

    def predict(self, X):
        '''预测'''

        # 对X中每个实例, 调用_predict进行预测, 收集结果并返回.
        return np.apply_along_axis(self._predict, axis=1, arr=X)


if __name__ == '__main__':
    X = np.array([[1,0,1],[1,1,0],[1,1,1],[0,1,1],[0,0,1],[1,0,1],[1,1,0],[0,1,0],[0,0,0],[1,0,0]])
    y = np.array([1,1,1,1,1,0,0,0,0,0])
    Byes = BernoulliNavieBayes()
    Byes.train(X,y)
    y_pre = Byes.predict(X)
    print('Results:',y_pre)

    '''
    Results: [1 0 1 1 1 1 0 0 0 0]

    Process finished with exit code 0

    '''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值