vlambda博客
学习文章列表

使用朴素贝叶斯分类算法构建鸢尾属分类器

朴素贝叶斯分类算法利用样本数据建立概率模型,模型依据输入的一组特征标签或特征值,预测该组特征值所属的类别。


下面是一组观众喜爱电视栏目分类样本数据:

表中每行是一个样本数据,每一列是观众的特征标签,特征标签为“/”说明该观众没有该特征标签。节目有三个类别,分别是影视、财经和访谈。

问题:依据样本数据,推测具有下列特征标签的观众最大可能喜欢哪个电视栏目?

特征标签:(名人访谈、财经新闻、新闻直播间、影视剧场)

通过观察样本数据,具有上述特征标签的观众最大可能喜欢财经栏目。但机器无法像人一样使用眼睛观察数据,它需要从样本数据中找到特征标签和类别的关系,然后来推断该组特征标签属于哪个类别的可能性,这个关系就是概率模型。

设(tag1,tag2,tag3,tag4,tag5,tag6)为样本数据的样本空间S,(影视,财经,访谈)为样本数据的一个划分(B1,B2,B3)。则样本空间S的任意一个组合,必对应B1,B2,B3中的一个。

例如:

样本空间S的组合(电影频道,新闻直播间 ,影视剧场 ,财经新闻,焦点人物)对应B1(影视);组合(电影频道,财经新闻,新闻直播间,焦点人物)对应B2(财经);组合(新闻直播间,名人访谈      ,焦点人物)对应B3(访谈)。

定义了样本数据的样本空间S和样本数据的一个划分(B1,B2,B3),并设问题中的特征标签为样本空间S的组合A,上述问题可描述为:

使用朴素贝叶斯分类算法构建鸢尾属分类器                                             

即计算组合(也称为事件)A发生时,B(i)发生的概率。可分别计算B(1)、B(2)、B(3)在A发生后的概率,选择概率最大的B(i)为A的所属类别。

英国数学家托马斯·贝叶斯给出的贝叶斯公式可以计算B(1)、B(2)、B(3)在A发生后的概率,贝叶斯公式为:

使用朴素贝叶斯分类算法构建鸢尾属分类器

其中,i=1,2,……,n。

要理解贝叶斯公式,先要弄清楚P(B(i)|A)和P(A|B(i))的关系,通过样本数据可以计算出P(A|B(i))的条件概率,即B(i)发生时A发生的概率,即:

使用朴素贝叶斯分类算法构建鸢尾属分类器

把相关数据套入公式:

使用朴素贝叶斯分类算法构建鸢尾属分类器

得:

使用朴素贝叶斯分类算法构建鸢尾属分类器

把相关数据套入公式:

使用朴素贝叶斯分类算法构建鸢尾属分类器

得:

使用朴素贝叶斯分类算法构建鸢尾属分类器

其中B(0),A(0),A(1),A(2),A(3)都是随机变量,需要求出它们的联合概率。即计算出B(0)=影视且A(0)=名人访谈且A(1)=财经新闻且A(2)=新闻直播间且A(3)=影视剧场的概率。

把相关数据套入公式:

使用朴素贝叶斯分类算法构建鸢尾属分类器

得:

使用朴素贝叶斯分类算法构建鸢尾属分类器

分别求出P(B(i)A)和P(B(i)),即可得出P(A|B(i))的概率。

下面来理顺P(B(i)|A)、P(A|B(i))和P(B(i))三个公式之间的关系。P(B(i)|A)为后验概率,即A发生后B(i)发生的可能性;P(B(i))为先验概率,即通过分析样本数据获取的概率;P(A|B(i))是拟然估计(可能性估计),它也可以通过分析样本数据得到,即B(i)发生后,A发生的可能性。

理顺了三个公式之间的关系,再来理解贝叶斯公式就比较容易了。似然估计用来估计在样本数据内B(i)产生结果A的概率,用此概率除以B(i)在样本数据内发生的概率,结果即为A属于B(i)的概率。

贝叶斯公式的核心思想是利用先验概率来倒推后验概率,似然估计也属于先验概率,因为它也可以通过分析样本数据得到。

在计算拟然估计时,若特征标签过多,计算特征标签的联合概率会有较大的计算开销。在实际应用中,若每个特征标签为独立的随机变量,计算特征标签的联合概率就会转化为计算每个特征标签的先验概率,计算过程显然简单方便了许多,在这种情况下,贝叶斯公式称为朴素贝叶斯公式。

使用朴素贝叶斯分类算法构建鸢尾属分类器

下面使用朴素贝叶斯公式分别计算下面的概率:

使用朴素贝叶斯分类算法构建鸢尾属分类器

分别计算P(影视)、P(财经)、P(访谈)的概率,它们的概率计算非常简单,用样本中出现的类别次数除以样本总数量。

P(影视) = 2/6 ≈ 0.33

P(财经) = 3/6 = 0.5

P(访谈) = 1/6 ≈ 0.17

分别计算P(名人访谈|影视)、P(财经新闻|影视)、P(新闻直播间|影视)、P(影视剧场|影视)的概率:

P(名人访谈|影视) = P(影视)* P(名人访谈)/P(影视) = 3/6 = 0.5

P(财经新闻|影视)= P(影视)* P(财经新闻)/P(影视) = 5/6 ≈ 0.83

P(新闻直播间|影视)= P(影视)* P(新闻直播间)/P(影视) = 5/6 ≈ 0.83

P(影视剧场|影视)= P(影视)* P(影视剧场)/P(影视) =2/6≈ 0.33

从上面的计算过程可得出P(特征标签|类别)的概率即为P(特征标签)的概率。

为后面简述方便,设特征标签(名人访谈,财经新闻,新闻直播间,影视剧场)别名为TAG。名人访谈别名为M,财经新闻别名为C,新闻直播间别名为X,影视剧场别名为Y。

P(影视|TAG) 计算公式的分母为:

P(影视)*P(M|影视)* P(C|影视)* P(X|影视)* P(Y|影视)

= 0.33 * 0.5 * 0.83 * 0.83 * 0.33

=0.037

P(影视|TAG) 计算公式的分子为:

P(影视)* P(M|影视)* P(C|影视)* P(X|影视)* P(Y|影视)+ P(财经)* P(M|财经)* P(C|财经)* P(X|财经)* P(Y|财经)+ P(访谈)* P(M|访谈)* P(C|访谈)* P(X|访谈)* P(Y|访谈)

≈ 0.037 + 0.057 + 0.019

≈ 0.113

P(影视|TAG) = 0.037/0.113≈0.327

同理可计算出:

P(财经|TAG)=0.057/0.113≈0.504

P(访谈|TAG)=0.019/0.113≈0.168

排序:

P(财经|TAG) > P(影视|TAG) > P(访谈|TAG)

由此可得,特征标签(名人访谈、财经新闻、新闻直播间、影视剧场)属于财经类别的可能性最大。

电视栏目分类是离散随机变量,若随机变量是连续实数,朴素贝叶斯分类算法该如何处理?

若特征是连续随机变量,可以假设该随机变量服从某个概率分布,使用训练数据来估计分布参数,下面通过朴素贝叶斯分类算法构建鸢尾属分类器。

鸢尾属数据集在K-近邻算法使用过,下面再简单介绍一下鸢尾属数据集。

鸢尾属数据集由埃德加·安德森建立,数据集包含了setosa 、versicolor 、virginica种类各 50个样本。

鸢尾属分类器以鸢尾属数据集为样本数据,将数据集分为两部分:一部分用于归类训练,一部分用于归类测试。

训练数据集为:train_Iris.csv

测试数据集为:test_ Iris.csv

样本数据样例:

使用朴素贝叶斯分类算法构建鸢尾属分类器

鸢尾属数据集的特征值都是连续实数,每个特征是连续的随机变量。一般说来,当我们缺乏关于某个实数随机变量分布的先验知识,而不知道如何选择何种形式的概率分布时,正态分布是较好的选择。因为在客观实际中,有许多随机变量,它们是由大量的相互独立的因素影响所形成的,而其中的每一个因素在总的影响中所起的作用是微小的,这种随机变量往往近似地服从正态分布。

我们使用正态分布来描述鸢尾属特征变量的概率分布,正态分布的概率密度公式为:

使用朴素贝叶斯分类算法构建鸢尾属分类器

其中μ为均值,σ^2为方差,σ为标准差。

从概率密度公式可以看出,只要计算出样本数据的均值和标准差,就可以确定样本数据的概率密度公式,从而确定样本数据的概率分布。

应用朴素贝叶斯分类算法构建构建鸢尾属分类器的基本思想:

计算出样本数据每个特征列分属不同类别的正态分布概率密度函数(确定均值和标准差),即通过样本数据为:

使用朴素贝叶斯分类算法构建鸢尾属分类器

建立概率模型:

使用朴素贝叶斯分类算法构建鸢尾属分类器

概率模型为目标数据特征值所属同一类别的概率密度值之乘积。其中m=4是样本数据的特征数量,x(j)为第j个特征值,σ为第j个特征值所所属同一类别的标准差,μ为第j个特征值所属同一类别的均值。

先验概率模型为:

使用朴素贝叶斯分类算法构建鸢尾属分类器

其中B(i)为Iris-setosa、Iris-versicolor、Iris-virginica类别之一,在鸢尾属样本数据集中三个类别的先验概率相等,在计算过程中可以忽略先验概率。

朴素贝叶斯公式的分母:

使用朴素贝叶斯分类算法构建鸢尾属分类器

该公式计算目标数据特征值分属不同类的概率密度值之乘积的累加和,在计算目标数据分属不同分类的概率分布中,该公式的计算结果完全相同,因此朴素贝叶斯公式的分母也可以忽略。

朴素贝叶斯公式只需计算:

确定样本数据所有特征列分属不同类别的正态分布概率密度函数就可以了。

最后通过前面建立的概率模型分别计算目标数据特征值所属不同类别的正态分布联合概率密度值,排序联合概率密度值,联合概率密度值最大的为目标数据的类别。

具体计算过程:

(1)计算样本数据每个特征列分属不同类别的均值和标准差。如计算花萼长度、花萼宽度、花瓣长度、花瓣宽度分别属于Iris-setosa、Iris-versicolor、Iris-virginica类别的均值和标准差。确定了均值和标准差,也就确定了每个特征列分属不同类别的正态分布概率密度函数;

(2)计算目标数据特征值(花萼长度、花萼宽度、花瓣长度、花瓣宽度)分属Iris-setosa、Iris-versicolor、Iris-virginica类别的联合概率密度值,即分别计算目标数据分属Iris-setosa、Iris-versicolor、Iris-virginica类别的概率密度值。

(3)排序联合概率密度值,联合概率密度值最大的为目标数据的类别。

例1 使用朴素贝叶斯分类算法构建构建鸢尾属分类器


import numpy as np
# 计算正态分布概率密度值
# x:特征值
# mean:均值
# stdev:标准差
def calcu_normal(x,mean,stdev):
    exp = np.exp(-(np.power(x-mean,2))/(2*np.power(stdev,2)))
    nd = (1/(np.sqrt(2*np.pi)*stdev))*exp
    return nd
  
# 鸢尾属类别
iris_category = ["Iris-setosa","Iris-versicolor","Iris-virginica"]
  
# 存储类别数据
iris_category_data = {"Iris-setosa":[],"Iris-versicolor":[],"Iris-virginica":[]}
# 存储同一类别不同特征的均值和标准差
iris_category_mean = {"Iris-setosa":[],"Iris-versicolor":[],"Iris-virginica":[]}
  
  
# 计算目标数据特征变量正态分布联合概率密度值
# feature:目标数据特征列表
# key: 类别
def calcu__normal_density(feature,key):
    density = 1
    for i in range(len(feature)):
       density *= calcu_normal(feature[i],iris_category_mean[key][i][0],iris_category_mean[key][i][1])
    return density
  
# 程序入口
if __name__ == '__main__':
  
   # 读取训练集特征数据
   feature_data = np.genfromtxt('train_Iris.csv',delimiter=',',dtype='float',usecols=[0,1,2,3])
   # 读取训练集类别名称
   category_data = np.genfromtxt('train_Iris.csv',delimiter=',',dtype='str',usecols=[4])
   # 读取目标数据集
   dest_data = np.genfromtxt('test_Iris.csv',delimiter=',',dtype='float',usecols=[0,1,2,3])
   # 按类别划分数据
   for item in iris_category:
       count = np.array(range(list(category_data).count(item)))
       start_index = list(category_data).index(item)
       end_index = start_index + len(count)
       # 花萼长度
       category = feature_data[start_index:end_index,0]
       iris_category_data[item].append(category)
       # 花萼宽度
       category = feature_data[start_index:end_index,1]
       iris_category_data[item].append(category)
       # 花瓣长度
       category = feature_data[start_index:end_index,2]
       iris_category_data[item].append(category)
       # 花瓣宽度
       category = feature_data[start_index:end_index,3]
       iris_category_data[item].append(category)
  
   # 计算样本数据每个特征列分属不同类别的均值和标准差
   for key in  iris_category_data:
       for v in iris_category_data[key]:
           # 计算均值和方差
           meanstd = [np.mean(v),np.std(v,ddof=1)]
           iris_category_mean[key].append(meanstd)
            
  
   # 计算目标数据集每个样本属于某个类别的概率密度
   for dest_v in dest_data:
       dic_density = {"Iris-setosa":0,"Iris-versicolor":0,"Iris-virginica":0}
       for key in dic_density:
          density = calcu__normal_density(dest_v,key)
          dic_density[key] = density
       # 排序
       dic_density = sorted(dic_density.items(), key = lambda kv:(kv[1], kv[0]),reverse=True)
       # 输出目标数据dest_v所属类别
       print(dest_v,end=":")
       print(dic_density[0])


执行构建的朴素贝叶斯鸢尾属分类器,对test_ Iris.csv测试集的33项目标数据进行了自动归类测试,正确归类33项,归类正确率为100%。

K—近邻算法每次对目标数据进行分类时都会遍历整个样本数据集,而朴素贝叶斯会通过样本数据预先建立概率模型,计算工作量要小于K—近邻算法。对于鸢尾属分类器来说,朴素贝叶斯分类算法的性能要优于K—近邻算法。



文中案例代码和数据集可在编程训练营APP下载。





END





编程训练营APP
创新在线学习模式,学习编程不再半途而废
安卓手机应用商店
搜索编程训练营下载