朴素贝叶斯分类器
Naive Bayesian Classifier
C 语言实现
信息电气工程学院计算本1102班 马 振 磊
[1**********]
1. 贝叶斯公式
通过贝叶斯公式,我们可以的知在属性F1-Fn 成立的情况下,该样本属于分类C 的概率。 而概率越大,说明样本属于分类C 的可能性越大。
若某样本可以分为2种分类A ,B 。
要比较P(A | F1,F2......) 与 P(B | F1,F2......)的大小只需比较,P(A)P(F1,F2......| A) ,与P(B)P(F1,F2......| B) 。 因为两式分母一致。
而P(A)P(F1,F2......| A)可以采用缩放为P(A)P(F1|A)P(F2|A).......(Fn|A)
因此,在分类时,只需比较每个属性在分类下的概率累乘,再乘该分类的概率即可。
以上是根据天气的4种属性,某人外出活动的记录。 若要根据以上信息判断
(Outlook = sunny,Temprature = cool,Humidity = high,Wind = strong) 所属分类。
P(yes| sunny ,cool ,high ,strong )=P(yes)P(sunny|yes)P(cool |yes)P(high|yes)P(strong|yes)/K P(no| sunny ,cool ,high ,strong )=P(no)P(sunny|no)P(cool |no)P(high|no)P(strong|no)/K
K 为缩放因子,我们只需要知道两个概率哪个大,所以可以忽略K 。
P(yes)=9/14 P(no)=5/14
P(sunny|yes)=2/9 P(cool|yes)=1/3 P(high|yes)=1/3 P(strong|yes)=1/3 P(sunny|no)=3/5 P(cool|no)=1/5 P(high|no)=4/5 P(strong|no)=3/5
P(yes| sunny ,cool ,high ,strong)=9/14*2/9*1/3*1/3*1/3=0.00529 P(no| sunny ,cool ,high ,strong )=5/14*3/5*1/5*4/5*3/5=0.20571 No 的概率大,所以该样本实例属于no 分类。
2. 数据结构及代码实现
1. 属性及分类
我们限定分类器的属性不大于9个,每个属性拥有不大于9个值。于是,我们考虑采用一个9 X 9的表格存储属性及其值。
为了调用数据方便,我们把数据从第一行开始储存。为了充分利用存储空间,我们把第零行储存分类数据。
现在,我们可以采用一个10 X 10 的表格来储存数据了。而每个单元格的内容需要占用一定的储存空间,我们可以用一个三维数组char feature[10][10][10]来表示这种结构的数据。用来容纳9个属性的9个值。第0行,我们用来储存分类数据。而第一行的第一列没有被使用,而其中含有10个char 类型的数据我们可以用它来储存属性值的多少。 前一段的数据:
分类: yes no 属性outlook : sunny overcast rain 属性temperature : hot mild cool 属性humidity : high normal 属性wind : strong weak
代码如下:
int x=1,y;
printf("请输入属性名称(小于9个字符):"); gets(feature[x][0]);
printf("该属性有几种值(不多于9个值):");
scanf("%c",&feature[0][0][x]); //把属性值储存入feature[0][0][x]; feature[0][0][x]-=48; //feature[0][0][x]是由字符格式输入的-48变为数字
getchar();
system("cls"); 数组
printf("该事物可以被分为几种类别:"); scanf("%c",&feature[0][0][0]); feature[0][0][0]-=48; getchar();
system("cls");
for(y=1;y
//分类数目存入feature[0][0][0]
for(y=1;y
printf("请输入第%d个值:",y); gets(feature[x][y]); } x++;
通过这段代码的循环,输入属性及其值进入feature 数组。
通过以下代码将分类数据存入数组第0行。
//通过循环将分类存入第0行
printf("请输入第%d种类别的名称:",y); gets(feature[0][y]); }
2. 训练样本
同样,每个单元格里限制最多有9个字符,加上一个’\0’终止符,共十个。而样本数量,也就是行数,可以适当的多一点,暂设为30。因此我们采用三维数组char sample[30][10][10]来容纳样本数据。
X 的初始值为1
for(y=1;y
{
printf("特征%s的取值:",feature[y][0]); gets(sample[x-1][y]); }
printf("该样本归于哪一种分类:"); gets(sample[x-1][0]); x++;
SampleNum++;
//统计样本的数量
3. 计算概率
class probability{ public:
int id; double p;
probability() {
p=0; }
//给每个概率值一个定位ID ,方便查找
};
probability prob[729];
采用一729个类来存放每个属性值在不同分类下的概率。至多有9种属性,每个属性至多拥有9个值,而要计算这9个属性的9种值在9种不同分类下的概率,所以我们用了729个类。并且在构造函数里面初始化概率p 为0.
接下来,统计各种分类出现的个数。9种分类出现的数目,分别储存在SampleClassNum[9]的不同单元格里。 int SampleClassNum[9]={0,0,0,0,0,0,0,0,0}; for(c=1;c
if(strcmp(feature[0][c],sample[x][0])==0) SampleClassNum[c-1]++;
然后,我们可以开始计算概率了。
for(c=1;c
for(x=1;x
for(y=1;y
prob[counter].id=c*100+x*10+y; for(i=0;i
if(strcmp(feature[x][y],sample[i][x])==0 strcmp(feature[0][c],sample[i][0])==0)
}
&&
prob[counter].p++; //统计某一值在某一分类下的出现个数
以分类出 算出概率
prob[counter].p=prob[counter].p/SampleClassNum[c-1]; //出现个数除 //现总数,计
counter++; }
每个概率的ID 为3位整数,百位记录了分类信息,个位十位分别是,其属性值在表格中的X ,Y 坐标。 然后,进行比较,统计出出现个数,接着除以分类的出现总数,计算出概率。
4. 对新的实例进行分类
输入该新的实例。
char instance[9][10];
double Pinstance[9]={1,1,1,1,1,1,1,1,1}; int PID[9];
printf("贝叶斯分类器 Sept 5\n"); printf("请输入要分类的样本属性\n"); for(i=1;i
printf("特征%s的取值",feature[i][0]); gets(instance[i-1]); }
然后,计算出不含分类信息的值在表格中的X ,Y 坐标。
for(x=1;x
for(y=1;y
if(strcmp(feature[x][y],instance[x-1])==0) {
PID[x-1]=x*10+y; break; } }
根据X ,Y 坐标加上分类坐标,组成完整的3位数坐标。在概率表prob 中查找即可找到。通过累乘,然后乘上某一分类的概率,即可求出最终的概率。
for(c=1;c
for(y=0;y
for(i=0;i
if(prob[i].id==PID[y]+c*100) break;
Pinstance[c-1]=Pinstance[c-1]*prob[i].p; //累乘求概率 }
Pinstance[c-1]=Pinstance[c-1]*(SampleClassNum[c-1]/(double)SampleNum); //最后乘上这一分类的概率,即可求出最终概率 }
system("cls");
6. 输出各概率及分类
最后,比较各概率的大小,最大的所属分类,就是该实例的所属分类。
double t=0;
for(i=0;i
for(i=0;i
for(y=1;y
printf("%s的概率为:%lf\n",feature[0][y],Pinstance[y-1]);
朴素贝叶斯分类器
Naive Bayesian Classifier
C 语言实现
信息电气工程学院计算本1102班 马 振 磊
[1**********]
1. 贝叶斯公式
通过贝叶斯公式,我们可以的知在属性F1-Fn 成立的情况下,该样本属于分类C 的概率。 而概率越大,说明样本属于分类C 的可能性越大。
若某样本可以分为2种分类A ,B 。
要比较P(A | F1,F2......) 与 P(B | F1,F2......)的大小只需比较,P(A)P(F1,F2......| A) ,与P(B)P(F1,F2......| B) 。 因为两式分母一致。
而P(A)P(F1,F2......| A)可以采用缩放为P(A)P(F1|A)P(F2|A).......(Fn|A)
因此,在分类时,只需比较每个属性在分类下的概率累乘,再乘该分类的概率即可。
以上是根据天气的4种属性,某人外出活动的记录。 若要根据以上信息判断
(Outlook = sunny,Temprature = cool,Humidity = high,Wind = strong) 所属分类。
P(yes| sunny ,cool ,high ,strong )=P(yes)P(sunny|yes)P(cool |yes)P(high|yes)P(strong|yes)/K P(no| sunny ,cool ,high ,strong )=P(no)P(sunny|no)P(cool |no)P(high|no)P(strong|no)/K
K 为缩放因子,我们只需要知道两个概率哪个大,所以可以忽略K 。
P(yes)=9/14 P(no)=5/14
P(sunny|yes)=2/9 P(cool|yes)=1/3 P(high|yes)=1/3 P(strong|yes)=1/3 P(sunny|no)=3/5 P(cool|no)=1/5 P(high|no)=4/5 P(strong|no)=3/5
P(yes| sunny ,cool ,high ,strong)=9/14*2/9*1/3*1/3*1/3=0.00529 P(no| sunny ,cool ,high ,strong )=5/14*3/5*1/5*4/5*3/5=0.20571 No 的概率大,所以该样本实例属于no 分类。
2. 数据结构及代码实现
1. 属性及分类
我们限定分类器的属性不大于9个,每个属性拥有不大于9个值。于是,我们考虑采用一个9 X 9的表格存储属性及其值。
为了调用数据方便,我们把数据从第一行开始储存。为了充分利用存储空间,我们把第零行储存分类数据。
现在,我们可以采用一个10 X 10 的表格来储存数据了。而每个单元格的内容需要占用一定的储存空间,我们可以用一个三维数组char feature[10][10][10]来表示这种结构的数据。用来容纳9个属性的9个值。第0行,我们用来储存分类数据。而第一行的第一列没有被使用,而其中含有10个char 类型的数据我们可以用它来储存属性值的多少。 前一段的数据:
分类: yes no 属性outlook : sunny overcast rain 属性temperature : hot mild cool 属性humidity : high normal 属性wind : strong weak
代码如下:
int x=1,y;
printf("请输入属性名称(小于9个字符):"); gets(feature[x][0]);
printf("该属性有几种值(不多于9个值):");
scanf("%c",&feature[0][0][x]); //把属性值储存入feature[0][0][x]; feature[0][0][x]-=48; //feature[0][0][x]是由字符格式输入的-48变为数字
getchar();
system("cls"); 数组
printf("该事物可以被分为几种类别:"); scanf("%c",&feature[0][0][0]); feature[0][0][0]-=48; getchar();
system("cls");
for(y=1;y
//分类数目存入feature[0][0][0]
for(y=1;y
printf("请输入第%d个值:",y); gets(feature[x][y]); } x++;
通过这段代码的循环,输入属性及其值进入feature 数组。
通过以下代码将分类数据存入数组第0行。
//通过循环将分类存入第0行
printf("请输入第%d种类别的名称:",y); gets(feature[0][y]); }
2. 训练样本
同样,每个单元格里限制最多有9个字符,加上一个’\0’终止符,共十个。而样本数量,也就是行数,可以适当的多一点,暂设为30。因此我们采用三维数组char sample[30][10][10]来容纳样本数据。
X 的初始值为1
for(y=1;y
{
printf("特征%s的取值:",feature[y][0]); gets(sample[x-1][y]); }
printf("该样本归于哪一种分类:"); gets(sample[x-1][0]); x++;
SampleNum++;
//统计样本的数量
3. 计算概率
class probability{ public:
int id; double p;
probability() {
p=0; }
//给每个概率值一个定位ID ,方便查找
};
probability prob[729];
采用一729个类来存放每个属性值在不同分类下的概率。至多有9种属性,每个属性至多拥有9个值,而要计算这9个属性的9种值在9种不同分类下的概率,所以我们用了729个类。并且在构造函数里面初始化概率p 为0.
接下来,统计各种分类出现的个数。9种分类出现的数目,分别储存在SampleClassNum[9]的不同单元格里。 int SampleClassNum[9]={0,0,0,0,0,0,0,0,0}; for(c=1;c
if(strcmp(feature[0][c],sample[x][0])==0) SampleClassNum[c-1]++;
然后,我们可以开始计算概率了。
for(c=1;c
for(x=1;x
for(y=1;y
prob[counter].id=c*100+x*10+y; for(i=0;i
if(strcmp(feature[x][y],sample[i][x])==0 strcmp(feature[0][c],sample[i][0])==0)
}
&&
prob[counter].p++; //统计某一值在某一分类下的出现个数
以分类出 算出概率
prob[counter].p=prob[counter].p/SampleClassNum[c-1]; //出现个数除 //现总数,计
counter++; }
每个概率的ID 为3位整数,百位记录了分类信息,个位十位分别是,其属性值在表格中的X ,Y 坐标。 然后,进行比较,统计出出现个数,接着除以分类的出现总数,计算出概率。
4. 对新的实例进行分类
输入该新的实例。
char instance[9][10];
double Pinstance[9]={1,1,1,1,1,1,1,1,1}; int PID[9];
printf("贝叶斯分类器 Sept 5\n"); printf("请输入要分类的样本属性\n"); for(i=1;i
printf("特征%s的取值",feature[i][0]); gets(instance[i-1]); }
然后,计算出不含分类信息的值在表格中的X ,Y 坐标。
for(x=1;x
for(y=1;y
if(strcmp(feature[x][y],instance[x-1])==0) {
PID[x-1]=x*10+y; break; } }
根据X ,Y 坐标加上分类坐标,组成完整的3位数坐标。在概率表prob 中查找即可找到。通过累乘,然后乘上某一分类的概率,即可求出最终的概率。
for(c=1;c
for(y=0;y
for(i=0;i
if(prob[i].id==PID[y]+c*100) break;
Pinstance[c-1]=Pinstance[c-1]*prob[i].p; //累乘求概率 }
Pinstance[c-1]=Pinstance[c-1]*(SampleClassNum[c-1]/(double)SampleNum); //最后乘上这一分类的概率,即可求出最终概率 }
system("cls");
6. 输出各概率及分类
最后,比较各概率的大小,最大的所属分类,就是该实例的所属分类。
double t=0;
for(i=0;i
for(i=0;i
for(y=1;y
printf("%s的概率为:%lf\n",feature[0][y],Pinstance[y-1]);