机器学习-*-朴素贝叶斯

说明

贝叶斯定理

有事件A、事件B,其中事件B有 B 1 , B 2 , . . . , B n {B_1,B_2,...,B_n} B1,B2,...,Bn个互不相交的事件组成。
若我们要估计 P ( B i ∣ A ) P(B_i|A) P(BiA)发生的概率,那么我们根据条件概率公式
P ( B i ∣ A ) = P ( B i , A ) P ( A ) P(B_i|A)=\frac{P(B_i,A)}{P(A)} P(BiA)=P(A)P(Bi,A)
其中, P ( A ) = ∑ i = 1 n P ( A ∣ B i ) P ( B i ) P(A)=\sum_{i=1}^{n}P(A|B_i)P(B_i) P(A)=i=1nP(ABi)P(Bi) P ( B i , A ) = P ( A ∣ B i ) P ( B i ) P(B_i,A)=P(A|B_i)P(B_i) P(Bi,A)=P(ABi)P(Bi)
故有 P ( B i ∣ A ) = P ( A ∣ B i ) P ( B i ) ∑ i = 1 n P ( A ∣ B i ) P ( B i ) P(B_i|A)=\frac{P(A|B_i)P(B_i)}{\sum_{i=1}^{n}P(A|B_i)P(B_i)} P(BiA)=i=1nP(ABi)P(Bi)P(ABi)P(Bi)
这就是所谓的贝叶斯公式

朴素贝叶斯

朴素贝叶斯是基于贝叶斯定理与特征田间独立假设而进行学习的模型。
朴素贝叶斯有一个较强的前提条件:各个特征之间是独立的。
他的思想是利用贝叶斯定理来学习到数据的分布,属于生成模型的一种。他根据期望风险最小化推导出后验概率最大化,故B可以用极大似然估计和贝叶斯估计来找到模型的参数。
具体来说:假设 Y Y Y是我们的类别分布, X X X是我们已有的数据。我们在预测新的样本 x x x属于哪个类别时,做的工作就是计算 P ( Y k ∣ x ) P(Y_k|x) P(Ykx),其中 k _k k就是 Y Y Y的类别个数。因此我们就需要学习联合概率分布 P ( Y , X ) P(Y,X) P(Y,X)。学习出来了联合概率分布,我们就可以给一个输入的 x x x预测出其所属的类别 y y y

条件独立性假设

P ( X = x ∣ Y = Y k ) = ∏ j = 1 m P ( x j ∣ Y = Y k ) P(X=x|Y=Y_k) = \prod_{j=1}^mP(x^j|Y=Y_k) P(X=xY=Yk)=j=1mP(xjY=Yk)
m是指的x的特征数量

这里写的不是很好,对概率的知识了解的还是很浅,具体的推理可以看李航博士《统计学习方法》

Python实现代码

#!/usr/bin/python
# -*- coding:utf-8 -*-
"""
Author LiHao
Time 2018/11/2 16:17
"""
import os
import sys
import numpy as np
from dataset.dataUtils import load_mnist
from ml_learn.algorithm.base import Algorithm #自己写的一个抽象类

class NativeBayes(Algorithm):
    def __init__(self,nb_lambda = 0):
        #每个参数的概率
        self._parameters_prop = {}
        #类别名称及各个类别的概率
        self._labels_prop = {}
        #拉普拉斯平滑参数
        self._lambda = nb_lambda
        #类别前缀
        self._label_prefix = "C"
        #参数及特征前缀
        self._parameters_predix = "P"
        #训练数据总数
        self._data_num = 0
        #类别名称列表
        self._label_name_list = None
        #特征的取值集合,为map(set)嵌套
        self._features_set = {}

    def predict(self,x):
        """
        预测
        :param x:
        :return:
        """
        dx,fy = x.shape
        for i in range(dx):
            max_class_name = ""
            max_class_prop = 0.0
            for class_name,class_prop in self._labels_prop.items():
                likehood_prop = 1.0
                for j in range(fy):
                    current_data_name = self._parameters_predix + str(j) + "_" + str(x[i][j]) + "|" + class_name
                    if self._parameters_prop.get(current_data_name) is not None:
                        likehood_prop *= self._parameters_prop.get(current_data_name)
                    else:
                        likehood_prop *= 0.001
                current_prop = class_prop * likehood_prop
                if current_prop >= max_class_prop:
                    max_class_prop = current_prop
                    max_class_name = class_name
            print("The ",i,"'s data class is ",max_class_name," max prop is ",max_class_prop)

    def train(self,X,Y):
        """
        训练-贝叶斯估计方法
        :param X:
        :param Y:
        :return:
        """
        data_num,feature_num = X.shape
        self._data_num = data_num
        label_list = []
        for i in range(data_num):
            #读入类别标签
            label_name = self._label_prefix+str(Y[i])
            if self._labels_prop.__contains__(label_name):
                self._labels_prop[label_name] += 1
            else:
                self._labels_prop[label_name] = 1
                label_list.append(label_name)
            for j in range(feature_num):
                feature_name = self._parameters_predix+str(j)
                if self._features_set.__contains__(feature_name):
                    self._features_set[feature_name].add(str(X[i][j]))
                else:
                    self._features_set[feature_name] = set([str(X[i][j])])
                current_data_name = self._parameters_predix+str(j)+"_"+str(X[i][j])+"|"+label_name
                if self._parameters_prop.__contains__(current_data_name):
                    self._parameters_prop[current_data_name] += 1
                else:
                    self._parameters_prop[current_data_name] = 1
        self._label_name_list = label_list
        #求参数的概率值
        for key,value in self._parameters_prop.items():
            belong_class = key.split("|")[-1]
            belong_feature_name = key.split("_")[0]
            #数据的每个特征维度值的种类个数
            Sj = len(self._features_set[belong_feature_name])
            class_num = self._labels_prop[belong_class]
            self._parameters_prop[key] = (value*1.0+self._lambda)/(class_num+self._lambda*Sj)
        #求每个类别的概率值
        for key,value in self._labels_prop.items():
            self._labels_prop[key] = (value*1.0 + self._lambda)/(data_num + len(self._labels_prop)*self._lambda)
        print("LH -*- Train Done.")
        
def bayes_test():
    """
    这是用的李航博士书P50上的例子
    其中第二个维度取值是S M L 我把它们变成了1 2 3 
    得到结果和书上的结果是一致的
    nb_lambda = 0为极大似然估计  >0是贝叶斯估计
    """
    X = np.array([[1,1],[1,2],[1,2],[1,1],[1,1],[2,1],[2,2],[2,2],[2,3],[2,3],[3,3],[3,2],[3,2],[3,3],[3,3]])
    Y = np.array([[-1],[-1],[1],[1],[-1],[-1],[-1],[1],[1],[1],[1],[1],[1],[1],[-1]])
    T = np.array([[2,1]])
    import time
    start1 = time.time()
    clf = NativeBayes(nb_lambda=0)
    clf.train(X,Y)
    clf.predict(T)
    end1 = time.time()
    print(end1-start1)

if __name__ == '__main__':
    bayes_test()

这里用了李航《统计学习方法》中的例子来测试,证明其准确性
在这里插入图片描述
load_mnist函数 见我的另一篇博客中写的KNN手写数字分类
我也用上面得到的数据集做了朴素贝叶斯分类,但效果还不如KNN。部分原因是每一维数据是0-1之间离散的数值,没有做标准化。将其变为0或1的取值应该会提升一些效果。
听说,朴素贝叶斯用在文本分类中效果不错

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值