朴素贝叶斯法是基于贝叶斯定理与特征条件独立假设的分类方法。对于搞机器学习的同学们来说,这是相对简单但效果较好的模型。

朴素贝叶斯方法的理论

设输入为n维特征向量X={x1,x2,...,xn},输出为类标记集合Y={c1,c2,...ck}。朴素贝叶斯法通过训练数据集学习联合概率分布P(X,Y),其中X是n维,Y是分类标记。有了模型P(X,Y),要预测一个特征向量的分类标记,则分别计算P(X,Y=c1),P(X,Y=c2),...P(X,Y=ck),选择取最大值的p(X,Y=cm),将cm作为X的分类标记。但对于模型P(X,Y)中的X是n维随机变量,若每一维特征取值最少有两个值,那么模型P(X,Y)参数量将是指数级的,这在特征维度较大的时候是不可行的。朴素贝叶斯法是引入条件独立性假设,由条件概率可得:

            P(X=x,Y=ck)

            =P(X(1)=x(1),X(2)=x(2),...X(n)=x(n)|Y=ck)*P(Y=ck)

 (应用条件独立性假设)=P(X(1)=x(1)|Y=ck)*P(X(2)=x(2)|Y=ck)*...*P(X(n)=x(n)|Y=ck)*P(Y=ck)

          即   =P(Y=ck)*∏i=1..nP(X(i)=x(i)|Y=ck)

条件独立性假设等于说用于分类的特征在类确定的情况下都是条件独立的。通过条件独立性假设,朴素贝叶斯法是模型变得简单,参数数量大大减少,但也牺牲一定的分类准确率。

朴素贝叶斯参数估计-极大似然估计

计算先验概率P(Y=ck)

P(Y=ck)=(∑i=1..nI(yi=ck))/N   , k=1,2,...,K

其中I(yi=ck)为指示函数,当yi=ck时函数值等于1,否则为0。

计算条件概率P(X(j)=ajl|Y=ck)

P(X(j)=ajl|Y=ck)=(∑i=1..nI(xi(j)=ajl,yi=ck))/∑i=1..nI(yi=ck)   ,j=1,2,,,n; l=1,2,S;k=1,2,K

其中Sj是第j维特征的取值数。

由于计算条件概率可能会造成某个特征的计数为零,这样在预测分类的时候就会对有该特征的类计算值为0.为了避免这种情况,可采用拉普拉斯平滑处理。

预测分类

对给定的实例x=(x(1),x(2),...x(n))T,计算

P(Y=ck)*∏i=1..nP(X(i)=x(i)|Y=ck), k=1,2,...,K

然后根据上述K个结果,确定x的分类

y=argmax P(Y=ck)*∏i=1..n P(X(i)=x(i)|Y=ck)

例:

训练数据

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
x(1) 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
x(2) S M M S S S M M L L L M M L L
Y -1 -1 1 1 -1 -1 -1 1 1 1 1 1 1 1 -1

数据存储在文件中,每一行存储格式为<x(1) x(2) Y>,即特征1,特征2,分类属性以空格分隔。如下

1 S -1
1 M -1
1 M  1
1 S  1
1 S -1
2 S -1
2 M -1
2 M  1
2 L  1
2 L  1
3 L  1
3 M 1
3 M 1
3 L  1
3 L -1

代码如下:

/********************************************************************/
/*
朴素贝叶斯法
*/
/************************************************************************/
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include<vector>
#include<map>
#include<set>
using namespace std;
class naiveBayes{
public:
     //载入数据并统计分量计数  
void loadData(){
ifstream fin(dataFile.c_str());
if(!fin){
cout<<"数据文件打开失败"<<endl;
exit(0);
}
while(fin){
string line;
getline(fin,line);
if(line.size()>1){
stringstream sin(line);
string s[2];
int c;
sin>>s[0]>>s[1]>>c;
//cout<<s1<<" "<<s2<<" "<<c<<endl;
dataSize++;
if(ym.count(c)>0){
ym[c]++;
}else{
ym[c]=1;
}
for(int i=0;i<2;i++){
if(feam.count(s[i])>0){
if(feam[s[i]].count(c)>0){
feam[s[i]][c]++;
}else{
feam[s[i]][c]=1;
}
}else{
map<int,int> mt;
mt[c]=1;
feam[s[i]]=mt;
}
}
} } }
     //显示map模型
void dispModel(){
cout<<"训练数据总数"<<endl;
cout<<dataSize<<endl;
cout<<"分类统计计数"<<endl;
for(map<int,int>::iterator mi=ym.begin();mi!=ym.end();mi++){
cout<<mi->first<<" "<<mi->second<<endl;
}
cout<<"特征统计计数:"<<endl;
for(map<string, map<int,int> >::iterator mi=feam.begin();mi!=feam.end();mi++){
cout<<mi->first<<": ";
for(map<int,int>::iterator ii=mi->second.begin();ii!=mi->second.end();ii++){
cout<<"<"<<ii->first<<" "<<ii->second<<"> ";
}
cout<<endl;
}
}
     //预测分类
void predictive(){
string x1,x2;
cout<<"请输入测试数据(包括两维特征,第一维取值<1,2,3>;第二维取值<S,M,L>)"<<endl;
string a1[]={"1","2","3"};
string a2[]={"M","S","L"};
set<string> a1set(a1,a1+3);
set<string> a2set(a2,a2+3);
while(cin>>x1>>x2){
if(a1set.count(x1)>0&&a2set.count(x2)>0){
double py1=(double(ym[-1])/dataSize)*(double(feam[x1][-1])/ym[-1])*(double(feam[x2][-1])/ym[-1]);
double py2=(double(ym[1])/dataSize)*(double(feam[x1][1])/ym[1])*(double(feam[x2][1])/ym[1]);
cout<<"y=-1的得分为"<<py1<<endl;
cout<<"y=1的得分为"<<py2<<endl;
cout<<"<"<<x1<<","<<x2<<">"<<"所属分类为:";
if(py1>py2){
cout<<"-1";
}else{
cout<<"1";
}
cout<<endl;
cout<<endl;
cout<<"继续测试(ctrl+Z结束)"<<endl;
}else{
cout<<"输入特征为:第一维取值<1,2,3>;第二维取值<S,M,L>,空格分隔。输入有误,请重新输入"<<endl;
}
}
}
naiveBayes(string df="data.txt"):dataFile(df),dataSize(0){
}
private:
string dataFile;
int dataSize;
//分类->计数
map<int,int> ym;
//分类->( 特征->计数 )
map<string, map<int,int> >feam;
};
int main(){
naiveBayes nb;
nb.loadData();
nb.dispModel();
nb.predictive();
system("pause");
return 0;
}

程序运行结果:

本例中,参数估计采用的是贝叶斯估计,有时间再把拉普拉斯平滑加上。

朴素贝页斯分类法 c++实现的更多相关文章

  1. 亚马逊CEO贝索斯致股东信:阐述公司未来计划

    亚马逊CEO 杰夫·贝索斯(Jeff Bezos)今天发布年度股东信, 详细描述了亚马逊的产品.服务和未来计划,当然,信中并没有任何的硬数据,比如说亚马逊Kindle的销量等等.但这封信也包括一些颇令 ...

  2. ios项目里扒出来的json文件

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #000000 } p.p2 { margin: 0.0px 0. ...

  3. Github上关于iOS的各种开源项目集合(强烈建议大家收藏,查看,总有一款你需要)

    下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITableVie ...

  4. iOS及Mac开源项目和学习资料【超级全面】

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  5. iOS:iOS开发非常全的三方库、插件等等

    iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...

  6. iOS开发--iOS及Mac开源项目和学习资料

    文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...

  7. iOS、mac开源项目及库汇总

    原文地址:http://blog.csdn.net/qq_26359763/article/details/51076499    iOS每日一记------------之 中级完美大整理 iOS.m ...

  8. iOS、mac开源项目及库(感谢原作者的分享)

    目录 模糊效果 富文本 表相关 HUD与Toast 其他UI 其他动画 网络测试 网络聊天 Model 数据库 PDF 摄像照相视频音频处理 消息相关 消息推送服务器端 版本新API的Demo 测试及 ...

  9. iOS超全开源框架、项目和学习资料汇总--数据库、缓存处理、图像浏览、摄像照相视频音频篇

    iOS超全开源框架.项目和学习资料汇总--数据库.缓存处理.图像浏览.摄像照相视频音频篇 感谢:Ming_en_long 的分享 大神超赞的集合,http://www.jianshu.com/p/f3 ...

随机推荐

  1. unity3d NGUI入门(描述和使用插件参数)

    我用NGUI它是3.5.4,Unity3d版本号是4.3.4f需要 NGUI3.5.4 下载NGUI,这是破解版的,用于学习.假设是商用.请支持正版 插件的导入 1.NGUI的导入,双击NGUI Ne ...

  2. mac_开启ftp并访问

    [启动&关闭] mac下一般用smb服务来进行远程文件访问,但要用FTP的话,高版本的mac os默认关掉了,可以用如下命令打开: sudo -s launchctl load -w /Sys ...

  3. 教你一步一步部署.net免费空间OpenShift系列之四------绑定域名、使用CDN加速

    很抱歉这几天没有时间,有人问我怎么绑定域名的问题也没有答复,下面进入正题,惊闻ASP.Net要开源了,难道.Net春天要来了?不废话,上回书说,部署完毕ASP.Net网站后,直接访问不能访问(嗯,众所 ...

  4. 详细的图文介绍如何利用XAMPP本地建站的环境配置教程

    原文:详细的图文介绍如何利用XAMPP本地建站的环境配置教程 WordPress 是一个简便快捷,用途广,人气旺的一个开源的博客建站程序.很有很多等您去发现. 简便快捷:在性能上易于操作.易于浏览: ...

  5. 随记一个C的时间加减

    //Centos6 x86_64 #include <time.h>#include <stdio.h>#include <string.h>#include &l ...

  6. AngularJS应用开发思维之1:声明式界面

    这篇博客之前承接上一篇:http://www.cnblogs.com/xuema/p/4335180.html 重写示例:模板.指令和视图 AngularJS最显著的特点是用静态的HTML文档,就可以 ...

  7. addEventListener 与attachEvent

    第一:简单的通用方法(IE && FF) window.onload = function(){ var oDiv = document.getElementById("J_ ...

  8. android学习8(ListView高级使用)

    ListView在android更开放的,于是继续ListView说明使用. 首先创建一个android项目,项目名为ListViewTest. ListView的简单使用 改动布局文件,改动后代码例 ...

  9. HTML5----input-datalist输入框自己主动提示功能

    效果图: <label for="word_name">字母 : </label> <input id="word_name" n ...

  10. [译]内存中的Java数组是怎么样的

    (文章翻译自What does a Java array look like in memory?) Java中的数组存储了两个中的一个类型:原始类型的类或则是引用类型(比如指针) 当一个对象通过Ne ...