机器学习入门之机器学习:贝叶斯分类器(二)——高斯朴素贝叶斯分类器代码实现
小标 2018-11-28 来源 : 阅读 1065 评论 0

摘要:本文主要向大家介绍了机器学习入门之机器学习:贝叶斯分类器(二)——高斯朴素贝叶斯分类器代码实现,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

本文主要向大家介绍了机器学习入门之机器学习:贝叶斯分类器(二)——高斯朴素贝叶斯分类器代码实现,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。

一 高斯朴素贝叶斯分类器代码实现

网上搜索不调用sklearn实现的朴素贝叶斯分类器基本很少,即使有也是结合文本分类的多项式或伯努利类型,因此自己写了一遍能直接封装的高斯类型NB分类器,当然与真正的源码相比少了很多属性和方法,有兴趣的可以自己添加。代码如下(有详细注释):

class NaiveBayes():
    '''高斯朴素贝叶斯分类器'''

    def __init__(self):

        self._X_train = None
        self._y_train = None
        self._classes = None
        self._priorlist = None
        self._meanmat = None
        self._varmat = None

    def fit(self, X_train, y_train):
        
        self._X_train = X_train
        self._y_train = y_train
        self._classes = np.unique(self._y_train)                       #  得到各个类别
        priorlist = []
        meanmat0 = np.array([[0, 0, 0, 0]])
        varmat0 = np.array([[0, 0, 0, 0]])        for i, c in enumerate(self._classes):            # 计算每个种类的平均值,方差,先验概率
            X_Index_c = self._X_train[np.where(self._y_train == c)]        # 属于某个类别的样本组成的“矩阵”
            priorlist.append(X_Index_c.shape[0] / self._X_train.shape[0])  # 计算类别的先验概率
            X_index_c_mean = np.mean(X_Index_c, axis=0, keepdims=True)     # 计算该类别下每个特征的均值,结果保持二维状态[[3 4 6 2 1]]
            X_index_c_var = np.var(X_Index_c, axis=0, keepdims=True)       # 方差
            meanmat0 = np.append(meanmat0, X_index_c_mean, axis=0)         # 各个类别下的特征均值矩阵罗成新的矩阵,每行代表一个类别。
            varmat0 = np.append(varmat0, X_index_c_var, axis=0)
        self._priorlist = priorlist
        self._meanmat = meanmat0[1:, :]                                    #除去开始多余的第一行
        self._varmat = varmat0[1:, :]    def predict(self,X_test):
        
        eps = 1e-10                                                        # 防止分母为0
        classof_X_test = []                                                #用于存放测试集中各个实例的所属类别
        for x_sample in X_test:
            matx_sample = np.tile(x_sample,(len(self._classes),1))         #将每个实例沿列拉长,行数为样本的类别数
            mat_numerator = np.exp(-(matx_sample - self._meanmat) ** 2 / (2 * self._varmat + eps))
            mat_denominator = np.sqrt(2 * np.pi * self._varmat + eps)
            list_log = np.sum(np.log(mat_numerator/mat_denominator),axis=1)# 每个类别下的类条件概率相乘后取对数
            prior_class_x = list_log + np.log(self._priorlist)             # 加上类先验概率的对数
            prior_class_x_index = np.argmax(prior_class_x)                 # 取对数概率最大的索引
            classof_x = self._classes[prior_class_x_index]                 # 返回一个实例对应的类别
            classof_X_test.append(classof_x)        return classof_X_test    def score(self, X_test, y_test):
        
        j = 0
        for i in range(len(self.predict(X_test))):            if self.predict(X_test)[i] == y_test[i]:
                j += 1
        return ('accuracy: {:.10%}'.format(j / len(y_test)))

对于手动实现的高斯型NB分类器,利用鸢尾花数据进行测试,与调用sklearn库的分类器结果差不多,基本在93-96徘徊。这是由于多次进行二八切分,相当于多次留出法。为计算更准确精度,可进行交叉验证并选择多个评价方法,这里不再实现。

import numpy as npfrom sklearn import datasetsfrom sklearn.model_selection import train_test_splitfrom sklearn import preprocessing# 获取数据集,并进行8:2切分iris = datasets.load_iris()X = iris.datay = iris.target# print(X)X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)nb = NaiveBayes()nb.fit(X_train,y_train)print(nb.predict(X_test))print(nb.score(X_test,y_test))#输出结果如下:[0, 2, 1, 1, 1, 2, 1, 0, 2, 0, 1, 1, 1, 0, 2, 2, 2, 2, 0, 1, 1, 0, 2, 2, 2, 0, 1, 0, 1, 0]accuracy: 96.6666666667%

二 其他

基于属性条件独立性假设的朴素贝叶斯,在现实中往往很难成立,因此产生了“半朴素贝叶斯分类器”。其基本思想是适当考虑一部分属性间的相互依赖信息,从而既不需要进行完全联合概率计算,又不至于彻底忽略比较强的属性依赖关系。“独依赖估计”是最常用的一种策略,即假设每个属性在类别之外最多依赖一个其他属性。包括SPODE方法,TAN方法,AODE方法等。

np.unique():返回原来array中不重复元素组成的新array,元素从小到大。

y = np.array([1, 2, 9, 1,2,3])
classes = np.unique(y)                     # 返回y中所有不重复的元素组成的新array([1,2,3,9])print(classes)                             # 结果为np.array([1,2,3,9])

np.where():对array进行操作

'''
1. np.where(condition, x, y)
满足条件(condition),满足进行x操作,不满足进行y操作
'''a= np.array([[9, 7, 3], [4, 5, 2], [6, 3, 8]])
b=np.where(a > 5, 1, 0)               #对于a中的元素如果大于5,则改写成1,否则写成0.                print(b)
输出结果:
[[1 1 0]
 [0 0 0]
 [1 0 1]]'''
2. np.where(condition)
只有条件 (condition),没有x和y,则输出满足条件元素的坐标 (等价于numpy.nonzero)。
这里的坐标以tuple的形式给出,通常原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
'''c = np.array([[9, 7, 3], [4, 5, 2], [6, 3, 8]])
d = np.where(c > 5)                                                #条件为元素大于5print(d)
输出结果如下(元组):
(array([0, 0, 2, 2], dtype=int64), array([0, 1, 0, 2], dtype=int64)) 表示下表为 00,01 20,22的元素满足条件。

a = np.array([1,3,6,9,0])
b = np.where(a > 5)
print(b)
输出结果(array([2, 3], dtype=int64),)表示坐标为2和3的元素满足,注意末尾的逗号,表明一维时实质输出元组为二维,2_,3_只不过后面没有而已,a维数大于等于2时,元组和a维数相同。
输出的结果是可以直接作为数组下标。
x = np.array([[1, 5, 8, 1], [2, 4, 6, 8], [3, 6, 7, 9], [6, 8, 3, 1]])
print(x[b])  结果为x的第2,3行组成的数组[[3  6 7 9]  [6  8 3 1]],等价于x[[2,3]],x[2,3]为输出为元素9,x[[2],[3]]输出数组[9]。

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标人工智能机器学习频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程