机器学习算法:朴素贝叶斯

简介:

朴素贝叶斯(Naive Bayes)算法的核心思想是:分别计算给定样本属于每个分类的概率,然后挑选概率最高的作为猜测结果


假定样本有2个特征x和y,则其属于分类1的概率记作p(C1|x,y),它的值无法直接分析训练样本得出,需要利用公式间接求得。

wKiom1RWzpzAm1IXAAAhVCcT6T4904.jpg

其中p(Ci)表示训练样本中分类为Ci的概率,它等于Ci样本数除以样本总数。

p(x,y)表示满足2个特征的样本概率,它等于第1特征等于x且第2特征等于y的样本数除以样本总数。可以发现p(x,y)与当前在计算哪个分类概率是无关的,因此实际计算中可以忽略它,不会影响结果。

p(x,y|Ci)表示Ci分类中满足2个特征的样本概率,在朴素贝叶斯算法中,认为x与y是相互独立的,因此p(x,y|Ci)=p(x|Ci)*p(y|Ci),其中p(x|Ci)表示Ci分类的样本中第1个特征等于x的概率。


上面的例子中只给定了2维的情况,实际可以扩展到N维,由于假定各特征相互独立,因此p(w|Ci)总是可以分解求得的。


上C#代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
using  System;
using  System.Collections.Generic;
using  System.Linq;
 
namespace  MachineLearning
{
     /// <summary>
     /// 朴素贝叶斯
     /// </summary>
     public  class  NaiveBayes
     {
         private  List<DataVector< string >> m_TrainingSet;
         
         /// <summary>
         /// 训练
         /// </summary>
         /// <param name="trainingSet"></param>
         public  void  Train(List<DataVector< string >> trainingSet)
         {
             m_TrainingSet = trainingSet;
         }
         
         /// <summary>
         /// 分类
         /// </summary>
         /// <param name="vector"></param>
         /// <returns></returns>
         public  string  Classify(DataVector< string > vector)
         {
             var  classProbDict =  new  Dictionary< string double >();
             
             //得到所有分类
             var  typeDict =  new  Dictionary< string int >();
             foreach ( var  item  in  m_TrainingSet)
                 typeDict[item.Label] = 0;
                 
             //为每个分类计算概率
             foreach ( string  type  in  typeDict.Keys)
                 classProbDict[type] = GetClassProb(vector, type);
                 
             //找最大值
             double  max =  double .NegativeInfinity;
             string  label =  string .Empty;
             foreach ( var  type  in  classProbDict.Keys)
             {
                 if (classProbDict[type] > max)
                 {
                     max = classProbDict[type];
                     label = type;
                 }
             }
             return  label;
         }
         
         /// <summary>
         /// 分类(快速)
         /// </summary>
         /// <param name="vector"></param>
         /// <returns></returns>
         public  string  ClassifyFast(DataVector< string > vector)
         {
             var  typeCount =  new  Dictionary< string int >();
             var  featureCount =  new  Dictionary< string , Dictionary< int int >>();
             
             //首先通过一次遍历,得到所需要的各种数量
             foreach ( var  item  in  m_TrainingSet)
             {
                 if (!typeCount.ContainsKey(item.Label))
                 {
                     typeCount[item.Label] = 0;
                     featureCount[item.Label] =  new  Dictionary< int int >();
                     for ( int  i = 0;i < vector.Dimension;++i)
                         featureCount[item.Label][i] = 0;
                 }
                 
                 //累加对应分类的样本数
                 typeCount[item.Label]++;
                 
                 //遍历每个维度(特征),累加对应分类对应特征的计数
                 for ( int  i = 0;i < vector.Dimension;++i)
                 {
                     if ( string .Equals(vector.Data[i], item.Data[i]))
                         featureCount[item.Label][i]++;
                 }
             }
             
             //然后开始计算概率
             double  maxProb =  double .NegativeInfinity;
             string  bestLabel =  string .Empty;
             foreach ( string  type  in  typeCount.Keys)
             {
                 //计算p(Ci)
                 double  classProb = typeCount[type] * 1.0 / m_TrainingSet.Count;
                 
                 //计算p(F1|Ci)
                 double  featureProb = 1.0;
                 for ( int  i = 0;i < vector.Dimension;++i)
                     featureProb = featureProb * (featureCount[type][i] * 1.0 / typeCount[type]);
                     
                 //计算p(Ci|w),忽略p(w)部分
                 double  typeProb = featureProb * classProb;
                 
                 //保留最大概率
                 if (typeProb > maxProb)
                 {
                     maxProb = typeProb;
                     bestLabel = type;
                 }
             }
             return  bestLabel;
         }
         
         /// <summary>
         /// 获取指定分类的概率
         /// </summary>
         /// <param name="vector"></param>
         /// <param name="type"></param>
         /// <returns></returns>
         private  double  GetClassProb(DataVector< string > vector,  string  type)
         {
             double  classProb = 0.0;
             double  featureProb = 1.0;
             
             //统计训练样本中属于此分类的数量,用于计算p(Ci)
             int  typeCount = m_TrainingSet.Count(p =>  string .Equals(p.Label, type));
             
             //遍历每个维度(特征)
             for ( int  i = 0;i < vector.Dimension;++i)
             {
                 //统计此分类下符合本特征的样本数,用于计算p(Fn|Ci)
                 int  featureCount = m_TrainingSet.Count(p =>  string .Equals(p.Data[i], vector.Data[i]) &&  string .Equals(p.Label, type));
                 
                 //计算p(Fn|Ci)
                 featureProb = featureProb * (featureCount * 1.0 / typeCount);
             }
             
             //计算p(Ci|w),忽略p(w)部分
             classProb = featureProb * (typeCount * 1.0 / m_TrainingSet.Count);
             
             return  classProb;
         }
     }
}


代码中Classify方法以最直接直观的方式实现算法,易于理解,但是由于遍历次数太多,在训练样本较多时效率不佳。ClassifyFast方法减少了遍历次数,效率有一定提升。两者的基础算法是一致的,结果也一致。


需要注意实际运行中有可能遇到多个分类概率相同或者每种分类概率都是0的情况,此时一般是随便选取一个分类作为结果。但有时要小心对待,比如用贝叶斯识别垃圾邮件时,如果概率相同,甚至是两个概率相差不大时,都要按非垃圾邮件来处理,这是因为没识别出垃圾邮件造成的影响远小于把正常邮件识别成垃圾造成的影响。



还是用上回的毒蘑菇数据进行一下测试,这回减少点数据量,选取2000个样本进行训练,然后选取500个测试错误率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public  void  TestBayes()
{
     var  trainingSet =  new  List<DataVector< string >>();
     var  testSet =  new  List<DataVector< string >>();
     
     var  file =  new  StreamReader( "agaricus-lepiota.txt" , Encoding.Default);
     //读取数据
     string  line =  string .Empty;
     for ( int  i = 0;i < 2500;++i)
     {
         line = file.ReadLine();
         if (line ==  null )
             break ;
             
         var  parts = line.Split( ',' );
         var  p =  new  DataVector< string >(22);
         p.Label = parts[0];
         for ( int  j = 0;j < p.Dimension;++j)
             p.Data[j] = parts[j + 1];
             
         if (i < 2000)
             trainingSet.Add(p);
         else
             testSet.Add(p);
     }
     file.Close();
     
     //检验
     var  bayes =  new  NaiveBayes();
     bayes.Train(trainingSet);
     int  error = 0;
     foreach ( var  in  testSet)
     {
         var  label = bayes.ClassifyFast(p);
         if (label != p.Label)
             ++error;
     }
     Console.WriteLine( "Error = {0}/{1}, {2}%" , error, testSet.Count, (error * 100.0 / testSet.Count));
}


测试结果是错误率是0%,有点出乎意料。改变训练样本与测试样本,错误率会有变化,比如与上一篇相同条件时(7000个训练样本+1124个测试样本),测试出的错误率是4.18%,与随机猜测50%的错误率相比,已经相当精确了。








     本文转自 BoyTNT 51CTO博客,原文链接:http://blog.51cto.com/boytnt/1571102,如需转载请自行联系原作者

相关实践学习
基于Hologres轻量实时的高性能OLAP分析
本教程基于GitHub Archive公开数据集,通过DataWorks将GitHub中的项⽬、行为等20多种事件类型数据实时采集至Hologres进行分析,同时使用DataV内置模板,快速搭建实时可视化数据大屏,从开发者、项⽬、编程语⾔等多个维度了解GitHub实时数据变化情况。
阿里云实时数仓实战 - 用户行为数仓搭建
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求:熟练掌握 SQL 语法熟悉 Linux 命令,对 Hadoop 大数据体系有一定的了解 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
相关文章
|
4月前
|
机器学习/深度学习 数据采集 人工智能
20分钟掌握机器学习算法指南
在短短20分钟内,从零开始理解主流机器学习算法的工作原理,掌握算法选择策略,并建立对神经网络的直观认识。本文用通俗易懂的语言和生动的比喻,帮助你告别算法选择的困惑,轻松踏入AI的大门。
|
10月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
1045 6
|
5月前
|
机器学习/深度学习 存储 Kubernetes
【重磅发布】AllData数据中台核心功能:机器学习算法平台
杭州奥零数据科技有限公司成立于2023年,专注于数据中台业务,维护开源项目AllData并提供商业版解决方案。AllData提供数据集成、存储、开发、治理及BI展示等一站式服务,支持AI大模型应用,助力企业高效利用数据价值。
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
AI训练师入行指南(三):机器学习算法和模型架构选择
从淘金到雕琢,将原始数据炼成智能珠宝!本文带您走进数字珠宝工坊,用算法工具打磨数据金砂。从基础的经典算法到精密的深度学习模型,结合电商、医疗、金融等场景实战,手把手教您选择合适工具,打造价值连城的智能应用。掌握AutoML改装套件与模型蒸馏术,让复杂问题迎刃而解。握紧算法刻刀,为数字世界雕刻文明!
221 6
|
7月前
|
机器学习/深度学习 算法 数据安全/隐私保护
基于机器学习的人脸识别算法matlab仿真,对比GRNN,PNN,DNN以及BP四种网络
本项目展示了人脸识别算法的运行效果(无水印),基于MATLAB2022A开发。核心程序包含详细中文注释及操作视频。理论部分介绍了广义回归神经网络(GRNN)、概率神经网络(PNN)、深度神经网络(DNN)和反向传播(BP)神经网络在人脸识别中的应用,涵盖各算法的结构特点与性能比较。
|
8月前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
1449 13
机器学习算法的优化与改进:提升模型性能的策略与方法
|
8月前
|
机器学习/深度学习 算法 网络安全
CCS 2024:如何严格衡量机器学习算法的隐私泄露? ETH有了新发现
在2024年CCS会议上,苏黎世联邦理工学院的研究人员提出,当前对机器学习隐私保护措施的评估可能存在严重误导。研究通过LiRA攻击评估了五种经验性隐私保护措施(HAMP、RelaxLoss、SELENA、DFKD和SSL),发现现有方法忽视最脆弱数据点、使用较弱攻击且未与实际差分隐私基线比较。结果表明这些措施在更强攻击下表现不佳,而强大的差分隐私基线则提供了更好的隐私-效用权衡。
212 14
|
7月前
|
人工智能 编解码 算法
使用 PAI-DSW x Free Prompt Editing图像编辑算法,开发个人AIGC绘图小助理
使用 PAI-DSW x Free Prompt Editing图像编辑算法,开发个人AIGC绘图小助理
136 0
|
7月前
|
机器学习/深度学习 人工智能 自然语言处理
解锁机器学习的新维度:元学习的算法与应用探秘
元学习作为一个重要的研究领域,正逐渐在多个应用领域展现其潜力。通过理解和应用元学习的基本算法,研究者可以更好地解决在样本不足或任务快速变化的情况下的学习问题。随着研究的深入,元学习有望在人工智能的未来发展中发挥更大的作用。
|
9月前
|
算法
PAI下面的gbdt、xgboost、ps-smart 算法如何优化?
设置gbdt 、xgboost等算法的样本和特征的采样率
241 2

热门文章

最新文章