【机器学习算法】手撕朴素贝叶斯分类器

2019年携程笔试的时候让手写朴素贝叶斯分类器,虽然清楚原理,但是没上手实践过,在考场上就发挥得很凌乱。

朴素贝叶斯原理较为简单,给定训练数据后,直接计算先验概率和条件概率(类别确定的情况下,某特征取特定值的概率),然后把新的数据分给后验概率最大的类。

其中求条件概率时候,python中defaultdict数据结构可以很方便的统计各个特征的各个取值的个数,可以把dict的value初始化为0。

来看一看defaultdict 和 dict 的区别吧~

>>> a = defaultdict(int)
>>> a
defaultdict(<class 'int'>, {})

>>> b = dict()
>>> b
{}

# 同样的操作,a没有报错,b报错了
>>> a[1] += 1
>>> a
defaultdict(<class 'int'>, {1: 1})

>>> b[1] += 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 1

例题是李航的统计学习方法中的Page:50-51

anyway,这只是一个基础的框架,还可以继续优化,比如连续特征离散化,类别数超过2等等。。。

import numpy as np
from collections import defaultdict
# 训练数据为15个样本
x1 = [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3]
x2 = [1, 2, 2, 1, 1, 1, 2, 2, 3, 3, 3, 2, 2, 3, 3]
y = [-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]
input = np.column_stack([x1, x2, y])
# 求样本点(2,1)的类别
new_data = [2, 1]

class Bayes_Classifier(object):
    '''

    构造朴素贝叶斯分类器

    '''
    def __init__(self, input, new_data):
        self.x = input[:, :-1]
        self.y = input[:, -1]
        self.prior_prob = self.compute_prior_prob()
        self.x1_d0, self.x1_d1 = self.compute_cond_prob(0)
        self.x2_d0, self.x2_d1 = self.compute_cond_prob(1)
        self.test_data = new_data

        
    def compute_prior_prob(self):
        '''

        先验概率的极大似然估计

        '''
        prior_prob = defaultdict(int)
        for i in range(len(self.y)):
            if self.y[i] == -1:
                prior_prob[-1] += 1
            else:
                prior_prob[1] += 1
        for key in prior_prob.keys():
            prior_prob[key] /= len(self.y)
    
        return prior_prob


    def compute_cond_prob(self, j):
        '''

        条件概率的极大似然估计
        <类确定的条件下,特征j取某值的概率>

        '''
        d0 = defaultdict(int)
        y0 = 0
        d1 = defaultdict(int)
        y1 = 0
        for n in range(self.x.shape[0]):
            if self.y[n] == -1:
                d0[self.x[n, j]] += 1
                y0 += 1
            else:
                d1[self.x[n, j]] += 1
                y1 += 1
        for key, value in d0.items():
            d0[key] = value / y0
        for key, value in d1.items():
            d1[key] = value / y1
        return d0, d1
    
    def max_pos_prob(self):
        '''

        最大化后验概率
        
        '''
        p0 = self.x1_d0[self.test_data[0]] * self.x2_d0[self.test_data[1]] * self.prior_prob[-1]
        p1 = self.x1_d1[self.test_data[0]] * self.x2_d1[self.test_data[1]] * self.prior_prob[1]
        return p0, p1



bayes = Bayes_Classifier(input, new_data)
# print(bayes.unique_y)
# print(bayes.x1_d0, bayes.x2_d0)
# print(bayes.x1_d1, bayes.x2_d1)
# print(bayes.prior_prob)
print(bayes.max_pos_prob())
发布了26 篇原创文章 · 获赞 13 · 访问量 7292

猜你喜欢

转载自blog.csdn.net/original_recipe/article/details/89160855