决策树ID3分类算法.docx
- 文档编号:8878789
- 上传时间:2023-02-02
- 格式:DOCX
- 页数:30
- 大小:507.10KB
决策树ID3分类算法.docx
《决策树ID3分类算法.docx》由会员分享,可在线阅读,更多相关《决策树ID3分类算法.docx(30页珍藏版)》请在冰豆网上搜索。
决策树ID3分类算法
决策树ID3分类算法
一、ID3算法介绍
决策树学习是一种逼近离散值目标函数的方法,在这种方法中学习到的函数被表示为一颗决策树。
ID3算法的思想就是自顶向下构造决策树,它使用统计测试来确定每一个实例属性单独分类训练样例的能力,继而判断哪个属性是最佳的分类属性,直到建立一棵完整的决策树。
利用这棵决策树,我们可以对新的测试数据进行分类。
2、算法的实现
算法实现了对于给定的数据信息,基于信息增益构造决策树,最后给出决策树和对训练数据集的分类准确率。
程序给定的测试样本如下:
实例序号
颜色
体形
毛型
类别
1
黑
大
卷毛
危险
2
棕
大
光滑
危险
3
棕
中
卷毛
不危险
4
黑
小
卷毛
不危险
5
棕
中
光滑
危险
6
黑
大
光滑
危险
7
棕
小
卷毛
危险
8
棕
小
光滑
不危险
9
棕
大
卷毛
危险
10
黑
中
卷毛
不危险
11
黑
中
光滑
不危险
12
黑
小
光滑
不危险
先对上述数据进行预处理:
保存为“data1.txt”
再运行程序,读入数据,输出分析过程和决策规则:
中间还有一些过程,为了节约资源,不复制过来了,下面是决策规则:
根据该规则,树形图如下:
3、程序代码及其部分注释
其中最核心的部分:
voidGenerate_decision_tree(Tree_Node*&root,vector
该函数由给定的训练数据产生一棵判定树。
完整代码:
#include
#include
#include
#include
#include
usingnamespacestd;
typedefstructtnode
{
chartdata[100];
}tnode;
typedefstructTree_Node
{
charname[100];
boolisLeaf;//标记是否叶子节点
vector
vector
}Tree_Node,*pTreeNpde;
typedefstructdnode
{
vector
}dnode;
typedefstructD_Node
{
vector
vector
tnodeclass_name;
}D_Node;
D_NodeG_DB;
pTreeNpdeRoot=NULL;
typedefstructFreeQNode
{
charname[100];
intcount;
vector
}FreeQNode;
typedefstructFreeQNodeDouble
{
charname[100];
intcount;
vector
vector
}FreeQNodeDouble;
typedefstructattr_node
{
intattr_id;
vector
vector
}attr_node;
vector
typedefstructbinNode
{
charname[100];
intcount;
vector
structbinNode*lchild;
structbinNode*rchild;
}binNode;
typedefstructbinNodeDouble
{
charname[100];
intcount;
vector
structbinNodeDouble*lchild;
structbinNodeDouble*rchild;
vector
}binNodeDouble;
voidinsert_tree(binNode*&r,charstr[100])
{
if(NULL==r)
{
binNode*node=newbinNode;
strcpy(node->name,str);
node->count=1;
//printf("[%s,%d]\n",node->name,node->count);
node->lchild=node->rchild=NULL;
r=node;
}
else
{
if(strcmp(r->name,str)==0)
{
r->count++;
}
elseif(strcmp(r->name,str)<0)
{
insert_tree(r->lchild,str);
}
else
{
insert_tree(r->rchild,str);
}
}
}
voiddelete_bin_tree(binNode*&r)
{
if(r!
=NULL)
{
delete_bin_tree(r->lchild);
delete_bin_tree(r->rchild);
delete(r);
r=NULL;
}
}
voidBin_tree_inorder(binNode*r,vector
{
if(r!
=NULL)
{
Bin_tree_inorder(r->lchild,Fq);
FreeQNodeft;
//printf("%s,%d\n",r->name,r->count);
strcpy(ft.name,r->name);
ft.count=r->count;
for(inti=0;i
{
ft.Set_ID.push_back(r->Set_ID[i]);//保存子集对应的ID号
}
Fq.push_back(ft);//此处少了这条语句,造成结果无法返回
Bin_tree_inorder(r->rchild,Fq);
}
}
voidGet_attr(binNode*r,attr_node&attr)
{
if(r!
=NULL)
{
Get_attr(r->lchild,attr);
tnodet;
strcpy(t.tdata,r->name);
//printf("%s,%d\n",r->name,r->count);
attr.attr_name.push_back(t);
attr.count_list.push_back(r->count);//保存出现次数
Get_attr(r->rchild,attr);
}
}
voidinsert_tree_double(binNodeDouble*&r,intDB_ID,charattr_name[100],charclass_name[100])
{
if(NULL==r)
{
binNodeDouble*node=newbinNodeDouble;
strcpy(node->name,attr_name);
node->count=1;
node->row_id.push_back(DB_ID);
node->lchild=node->rchild=NULL;
FreeQNodefq;
strcpy(fq.name,class_name);
fq.count=1;
fq.Set_ID.push_back(DB_ID);//保存子集所对应的ID号
node->classes.push_back(fq);
r=node;
}
else
{
if(strcmp(r->name,attr_name)==0)
{
r->count++;
r->row_id.push_back(DB_ID);//这里也需要保存相应的ID号
boolfound=false;
for(inti=0;i
{
if(strcmp(r->classes[i].name,class_name)==0)
{
r->classes[i].count++;
r->classes[i].Set_ID.push_back(DB_ID);//保存子集对应的ID号
found=true;//发现相同的变量名,计数器增1,
break;//并退出循环
}
}
if(!
found)
{
FreeQNodefq;
strcpy(fq.name,class_name);
fq.count=1;
fq.Set_ID.push_back(DB_ID);//保存子集所对应的ID号
r->classes.push_back(fq);
}
}
elseif(strcmp(r->name,attr_name)<0)
{
insert_tree_double(r->lchild,DB_ID,attr_name,class_name);
}
else
{
insert_tree_double(r->rchild,DB_ID,attr_name,class_name);
}
}
}
voiddelete_bin_tree_double(binNodeDouble*&r)
{
if(r!
=NULL)
{
delete_bin_tree_double(r->lchild);
delete_bin_tree_double(r->rchild);
delete(r);
r=NULL;
}
}
voidBin_tree_inorder_double(binNodeDouble*&r,vector
{
if(r!
=NULL)
{
Bin_tree_inorder_double(r->lchild,Fq);
FreeQNodeDoubleft;
strcpy(ft.name,r->name);//保存候属性的名称
ft.count=r->count;
for(intk=0;k
{
ft.row_id.push_back(r->row_id[k]);
}
//printf("doubleTree.%s,%d\n",r->name,r->count);
for(inti=0;i
{
FreeQNodefq;
strcpy(fq.name,r->classes[i].name);
fq.count=r->classes[i].count;
for(intj=0;j
{
fq.Set_ID.push_back(r->classes[i].Set_ID[j]);//保存子集对应的ID号
}
ft.classes.push_back(fq);
}
Fq.push_back(ft);
ft.classes.erase(ft.classes.begin(),ft.classes.end());//使用完,必须清空
Bin_tree_inorder_double(r->rchild,Fq);
}
}
voidgetFqI(vector
{
binNode*root=NULL;
for(inti=0;i { insert_tree(root,G_DB.DB[S[i]].row[class_id].tdata); } Bin_tree_inorder(root,Fq); delete_bin_tree(root); } voidgetFqIA(vector { binNodeDouble*root=NULL; for(inti=0;i { insert_tree_double(root,S[i],G_DB.DB[S[i]].row[attr_id].tdata,G_DB.DB[S[i]].row[class_id].tdata); } Bin_tree_inorder_double(root,Fq); delete_bin_tree_double(root); } voidreaddata(char*filename) { charstr[1000]; FILE*fp; fp=fopen(filename,"r"); fgets(str,1000,fp); intlen=strlen(str); intattr_no=0;//属性个数 introw_num=0; if(str! =NULL) { row_num=1; } for(inti=0;i { if(str[i]=='\t') { attr_no++; } } attr_no++;//最后一个是回车,整个属性值+1 printf("%d\n",attr_no); while(fgets(str,1000,fp)! =NULL) { row_num++;//统计行数 } fclose(fp); fopen(filename,"r"); tnodet; for(i=0;i { fscanf(fp,"%s",t.tdata); G_DB.attr_name.push_back(t); printf("%s\n",t.tdata); } strcpy(G_DB.class_name.tdata,G_DB.attr_name[attr_no-1].tdata); for(intj=1;j { dnodedt; tnodetemp; for(inti=0;i { fscanf(fp,"%s",temp.tdata); dt.row.push_back(temp); } G_DB.DB.push_back(dt); dt.row.erase(dt.row.begin(),dt.row.end()); } printf("%d\n",G_DB.DB.size()); for(i=0;i { for(intj=0;j { printf("%s\t",G_DB.DB[i].row[j].tdata); } printf("\n"); } } doubleFnc_I(vector { //给定一个子集,计算其按照class_id所对应的分类属性进行分类时的期望I //printf("calledFnc_I(%d)\n",class_id); vector getFqI(S,class_id,Fq);//调用getFqI获取按照Class_id为分类标准的分类结果,当Fq中为一条数据时,则子集S都属于一个分类 //否则,从中找到出现此时最大的,作为返回结果 //printf("begintocomputeI\n"); doubletotal=0; for(inti=0;i { total+=Fq[i].count; //printf("%s,%d\n",Fq[i].name,Fq[i].count); } doubleresult=0; if(0==total) { return0; } for(i=0;i { doublep=Fq[i].count/total; result+=-1*(p*log(p)/log (2)); } //printf("FNC_Ireturn\n\n"); returnresult; } doubleFnc_IA(vector { //给定一个子集,计算其按照class_id所对应的分类属性进行分类时的期望I getFqIA(S,attr_id,class_id,Fq); doubletotal=0; for(inti=0;i { total+=Fq[i].count; } doubleresult=0; if(0==total) { return0; } boolpr=false; for(i=0;i { doublestotal=Fq[i].count; doublesresult=0; if(pr)printf("[%s,%d]\n",Fq[i].name,Fq[i].count); for(intj=0;j { if(pr)printf("%s,%d\n",Fq[i].classes[j].name,Fq[i].classes[j].count); for(intk=0;k { //printf("%d\t",Fq[i].classes[j].Set_ID[k]+1); } //printf("\n"); doublesp=Fq[i].classes[j].count/stotal;//计算子集的频率 sresult+=-1*(sp*log(sp)/log (2)); } result+=(stotal/total)*sresult; } if(pr)printf("\n"); returnresult; } intSelectBestAttribute(vector { //输入训练数据集Samples,候选属性列表attribute_list //分类属性标记class_id //返回best_attribute doublefi=Fnc_I(Samples,5); //printf("%lf\n",fi); doubleIA=999999999; intbest_attrib=-1; for(inti=0;i { vector doubletfa=Fnc_IA(Samples,attribute_list[i],class_id,fqd); //printf("%d,FIA=%lf\n",i,tfa); if(IA>tfa) { IA=tfa; best_attrib=i; } } //printf("%lf\n",IA); printf("gain(%d)=%lf-%lf=%lf\n",best_attrib,fi,IA,fi-IA); returnattribute_list[best_attrib]; } voidfnc_getattr(vector { binNode*root=NULL; for(inti=0;i { insert_tree(root,G_DB.DB[Samples[i]].row[att_id].tdata); } Get_attr(root,at); delete_bin_tree(root); } voidget_class_num_and_name(vector { attr_nodeat; binNode*ro
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 决策树 ID3 分类 算法