/*
朴素贝叶斯算法思想: 举个例子,假如某天是否要出去打网球,有两种选择:是和否,即最后分成两个类别。但是受3个因素的影响,分别是天气、温度和是否有风。天气有3个值:晴、多云和有雨。温度有3个值:高,正常和低。是否有风有两个值:是和否。假如样本A是{天气晴,温度正常,无风,打网球},样本B是{天气有雨,温度低,有风,不打网球},还有其他的样本,可以得到样本的某些先验概率,即已经知道了是否打网球的结果某因素出现的概率。然后利用到贝叶斯公式的一些转换(数学的知识不在这里推),计算后验概率,即知道因素的情况,估计打网球与不打网球各自的概率。
*/
#include<iostream>
#include<fstream>
#include<string>
#include<vector>
#include<map>
using namespace std;
vector<string> split(const string& src,const string& delimiter); /**分离字符串**/
void rejudge(); /**重新判断原输入数据的类别**/
vector<vector<string> > vect; /**二维容器**/
map<string,int> category; /**存放类别**/
map<string,double> pro_map; /**各种概率的map容器**/
int main(){
string strLine;
pro_map.clear();
ifstream readfile("weather.txt"); /**打开文件**/
if(!readfile){
cout<<"Fail to open file weather!"<<endl;
cout<<getchar();
return 0;
}
else{
cout<<"读取原始数据如下:"<<endl;
vector<vector<string> >::size_type st_x; /**二维容器x坐标**/
vector<string> temp_vect;
vector<string>::size_type st_y; /**二维容器y坐标**/
while(getline(readfile,strLine)){ /**读入数据**/
//cout<<strLine<<endl;
temp_vect=split(strLine,","); /**分离字符串**/
vect.push_back(temp_vect); /**存放到容器中**/
temp_vect.clear();
}
string temp_string;
vector<string>::size_type temp_size1=vect.size()-1; /**总行数**/
vector<string>::size_type temp_size2=vect[0].size();/**总列数**/
for(int i=0;i<temp_size1+1;i++)
{
for(int j=0;j<temp_size2;j++) cout<<vect[i][j]<<' ';
cout<<endl;
}
for(st_x=1;st_x<temp_size1+1;st_x++){
/**遍历二维容器,统计各种类别、属性|类别的个数,以便后面的
概率的计算(跳过第一行的属性标题) **/
for(st_y=0;st_y<temp_size2;st_y++){
if(st_y!=temp_size2-1){ /**统计每一行前面的属性,统计属性|类别的个数**/
temp_string=vect[0][st_y]+"="+vect[st_x][st_y]+"|"
+vect[0][temp_size2-1]+"="+vect[st_x][temp_size2-1];
pro_map[temp_string]+=1; /**map记录**/
}
else{
temp_string=vect[0][temp_size2-1]+"="+vect[st_x][temp_size2-1]; /**类别**/
pro_map[temp_string]+=1;
category[vect[st_x][temp_size2-1]]=1;
}
temp_string.erase();
}
}
string::size_type st;
cout<<"统计过程如下:"<<endl;
for(map<string,double>::iterator it=pro_map.begin();it!=pro_map.end();it++){
cout<<it->first<<":"<<it->second<<endl;
if((st=it->first.find("|"))!=string::npos){ /**计算概率**/
it->second=it->second/pro_map[it->first.substr(st+1)];
}
}
cout<<"计算概率过程如下:"<<endl;
for(map<string,double>::iterator it2=pro_map.begin();it2!=pro_map.end();it2++){
if((st=it2->first.find("|"))==string::npos){
pro_map[it2->first]=pro_map[it2->first]/(double)temp_size1; /**每个类别占比**/
}
cout<<it2->first<<":"<<it2->second<<endl;
}
rejudge();
}
cout<<getchar();
return 0;
}
vector<string> split(const string& src,const string& delimiter){
string::size_type st;
if(src.empty()) throw "Empty string!";
if(delimiter.empty()) throw "Empty delimiter"; /**字符串为空或者分隔符为空**/
vector<string> vect;
string::size_type last_st=0;
while((st=src.find_first_of(delimiter,last_st))!=string::npos){ /**找到第一个为分隔符的位置**/
if(st!=last_st) vect.push_back(src.substr(last_st,st-last_st)); /**分离出字符串,可能第一个为分隔符,跳过**/
last_st=st+1;
}
if(last_st!=src.size()){ /**最后可能还有一个字符串**/
vect.push_back(src.substr(last_st,string::npos));
}
return vect;
}
void rejudge(){
string temp_string;
double temp_pro;
map<string,double> temp_map; /**存放后验概率的临时容器**/
cout<<"经过简单贝叶斯算法重新分类的结果如下:"<<endl;
for(vector<vector<string> >::size_type st_x=1;st_x<vect.size();st_x++){
for(map<string,int>::iterator it=category.begin();it!=category.end();it++){
temp_pro=1.0;
temp_string=vect[0][vect[0].size()-1]+"="+it->first;
temp_pro*=pro_map[temp_string];/**计算每种类别的概率**/
temp_string.erase();
for(vector<string>::size_type st_y=0;st_y<vect[st_x].size();st_y++){
if(it==category.begin()&&st_y!=vect[st_x].size()-1)
cout<<vect[st_x][st_y]<<" ";
if(st_y!=vect[st_x].size()-1){
temp_string=vect[0][st_y]+"="+vect[st_x][st_y]+
"|"+vect[0][vect[0].size()-1]+"="+it->first;
temp_pro*=pro_map[temp_string];
temp_string.erase();
}
}
temp_map[it->first]=temp_pro;
}
string temp_string2;
temp_pro=0;
cout<<"后验概率:";
for(map<string,double>::iterator it2=temp_map.begin();it2!=temp_map.end();it2++){
cout<<it2->first<<":"<<it2->second<<" ";
if(it2->second>temp_pro){ /**找最大的后验概率**/
temp_string2.erase();
temp_string2=it2->first;
temp_pro=it2->second;
}
}
cout<<"归类:"<<vect[0][vect[0].size()-1]<<"="<<temp_string2<<endl;
}
}