C++--2

// tai_1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream.h>
#include <fstream.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iomanip.h>
const N=100;//N定义为给定训练数据的估计个数
const M=6;//M定义为候选属性的个数
const c=2;//定义c=2个不同类
const s_max=5;//定义s_max为每个候选属性所划分的含有最大的子集数
int av[M]={3,3,2,3,4,2};
int s[N][M+2],a[N][M+2];//数组s[j]用于记录第i个训练样本的第j个属性值
int path_a[N][M+1],path_b[N][M+1];//用path_a[N][M+1],path_b[N][M+1]记录每片叶子的路径
int count_list=M;//count_list用于记录候选属性个数
int count=-1;//用count_train+1记录训练样本数
int attribute_test_list1[M];//attribute代表属性
int leaves=1;


int ss[M][c][s_max];//用数组ss[k][j]表示第k个候选属性划分的子集sj中类ci的样本数,数组的具体大小可根据给定训练数据调整
double p[M][c][s_max];//第k个候选属性划分的子集sj中样本属于类ci的概率
int count_s[M][s_max];//count_s[j]用于记录第i个候选属性的第j个子集中样本个数
double E[M];
double Gain[M];//分别定义E[M]和Gain[M]表示熵和增益(期望压缩)

double max_Gain;//变量max_Gain用于存储最大的信息增益
int Trip=-1;//用Trip记录每个叶子递归次数
int most;


void main()
{
 int i,j=-1,k,temp,l,count_test,true_class=0,count;
 char trainname[256],testname[256];
 int test[N][8];
 cout<<"请输入训练集文件名:"<<endl;
 cin>>trainname;
 ifstream trainfile;
 trainfile.open(trainname,ios::in|ios::nocreate);
 if(!trainfile)
 {
  cout<<"Trainfile can't be open,please try again!"<<endl;
  
 }
 
 //读取训练集
    while (trainfile>>temp)
 {
  j=j+1;
  int k=j%(M+2);
  if(k==0||j==0) count+=1;
 
  //count为训练集第几个,k代表第几个属性
  switch(k)
  {
  case 0:s[count][0]=temp;
   break;
  case 1:s[count][1]=temp;
   break;
  case 2:s[count][2]=temp;
   break;
      case 3:s[count][3]=temp;
   break;
  case 4:s[count][4]=temp;
   break;
     case 5:s[count][5]=temp;
   break;
  case 6:s[count][6]=temp;
   break;
  case 7:s[count][7]=temp;
   break;
  }
 }
    trainfile.close();
   
 //输出训练集
    for(i=0;i<=count;i++)
 {
  if(i%2==0)
   cout<<endl;
  for(j=0;j<M+2;j++)
   cout<<setw(4)<<s[j];
 }
 
 //most记录训练集中那类样本比较多,以用于确定递归终止时不确定的类别

 for( i=0,j=0,k=0;i<=count;i++)
 {  
  if(s[i][0]==0)j+=1;                                                  
  else k+=1;
 }
 if(j>k) most=0;
 else most=1;
  
 //count_train记录训练集的样本数

 
 //训练的属性
 for(i=0;i<M;i++)
  attribute_test_list1[i]=i+1;                                         

 //首次调用递归函数,即生成根节点的分支
void Generate_decision_tree(int b[][M+2],int bn,int attribute_test_list[],int sn,int ai,int aj);
     Generate_decision_tree(s,count+1,attribute_test_list1,count_list,0,0);
 cout<<endl<<"叶子节点个数为:"<<leaves<<endl;
 cout<<"请输入测试集文件名:";
  cin>>testname;
 ifstream testfile;
 testfile.open(testname,ios::in|ios::nocreate);
 if(!testfile)                                                          //train修改为test
 {
  cout<<"Trainfile can't be open,please try again!"<<endl;

 }
 count_test=0;
 j=-1;


 //读取测试集数据
    while (testfile>>temp)
 {
  j=j+1;
  k=j%(M+2);
  if(k==0) count_test+=1;
 
  //count为测试集第几个,k代表第几个属性
  switch(k)
  {
  case 0:test[count_test][7]=temp;
   break;
  case 1:test[count_test][1]=temp;
   break;
  case 2:test[count_test][2]=temp;
   break;
      case 3:test[count_test][3]=temp;
   break;
  case 4:test[count_test][4]=temp;
   break;
     case 5:test[count_test][5]=temp;
   break;
  case 6:test[count_test][6]=temp;
   break;
  }
 }
    testfile.close();
 for(i=1;i<=count_test;i++)
  test[i][0]=0;//以确保评估分类准确率 //0修改为i
 
 cout<<"count_test="<<count_test<<endl;
    cout<<"count_train="<<count<<endl;


 
 //用测试集来评估分类准确率
 for(i=1;i<=count_test;i++)
 {
  l=0;
     for(j=1;j<=leaves;j++)
   if(test[i][path_b[j][1]]==path_a[j][1]&&test[i][path_b[j][2]]==path_a[j][2]&&test[i][path_b[j][3]]==path_a[j][3]&&test[i][path_b[j][4]]==path_a[j][4]&&test[i][path_b[j][5]]==path_a[j][5]&&test[i][path_b[j][6]]==path_a[j][6])
   {
    l=1;
    if(test[i][7]==path_a[j][0]) true_class+=1;
      break;
   }
         if(test[i][7]==most && l==0) true_class+=1;
           break;
 }
     cout<<"true_class="<<true_class<<endl;
  cout<<"测试集与训练集比例为:"<<float(count)/count_test<<endl;
     cout<<"分类准确率为:"<<float(true_class)/count_test<<endl; 
  cout<<endl<<"叶子节点个数为:"<<leaves<<endl;

}
void Generate_decision_tree(int b[][M+2],int bn,int attribute_test_list[],int sn,int ai,int aj)
{
   //定义数组a记录目前待分的训练样本集,定义数组b记录目前要分结点中所含的训练样本集
   //same_class用来记数,判别samples是否属于同一个类
 
 Trip+=1;//用trip记录每一个叶子递归次数
 path_a[leaves][Trip]=ai;
    path_b[leaves][Trip]=aj;
 int same_class,i,j,k,l,ll,lll;

 if(bn==0)
 {
  //待分结点的样本集为空时,加上一个树叶,标记为训练集中最普通的类
  //记录路径与前一路径相同的部分
  for(i=1;i<Trip;i++)
   if(path_a[leaves][i]==0)
   {
    path_a[leaves][i]=path_a[leaves-1][i];
    path_b[leaves][i]=path_b[leaves-1][i];
   }
   cout<<endl<<"IF ";
   for(i=1;i<Trip;i++)
    if(i==1)cout<<"a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
    else cout<<"^a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
   cout<<" THEN class="<<most;
   path_a[leaves][0]=most;
   
   //修改树的深度
   if(path_a[leaves][Trip]==av[path_b[leaves][Trip]-1])
    for(i=Trip;i>1;i--)
     if(path_a[leaves][i]==av[path_b[leaves][i]-1])Trip-=1;
     else
      break;
             Trip-=1;
    leaves+=1;

 }
 else
 {
        same_class=1;
  for(i=0;i<bn-1;i++)
   if(b[i][0]==b[i+1][0])
    same_class+=1;
        if(same_class==bn)
  {
   //待分样本集属于同一类时以该类标记
   //记录路径与前一路径相同的部分
   for(i=1;i<Trip;i++)
    if(path_a[leaves][i]==0)
    {
                    path_a[leaves][i]=path_a[leaves-1][i];
     path_b[leaves][i]=path_b[leaves-1][i];
    }
            cout<<endl<<"IF ";
   for(i=1;i<Trip;i++)
    if(i==1)
     cout<<"a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
    else
     cout<<"^a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
   cout<<" THEN class="<<b[0][0];
   path_a[leaves][0]=b[0][0];
           
   //修改树的深度
   if(path_a[leaves][Trip]==av[path_b[leaves][Trip]-1])
    for(i=Trip;i>1;i--)
     if(path_a[leaves][i]==av[path_b[leaves][i]-1])Trip-=1;
     else
      break;
             Trip-=1;
    leaves+=1;
    //未分类的样本集减少
             for(i=0,l=-1;i<=count;i++)
    {
     for(j=0,lll=0;j<bn;j++)
      if(s[i][M+1]==b[j][M+1])
       lll++;
         if(lll==0)
      {
       l+=1;
       for(ll=0;ll<M+2;ll++)
        a[l][ll]=s[l][ll];
      }
    }
    for(i=0,k=-1;i<l;i++)
    {
     k++;
     for(ll=0;ll<M+2;ll++)
      s[k][ll]=a[i][ll];
    }
             count-=bn;

  }
  else
  {
   if(sn==0)
   {
    //候选属性集为空时,标记为训练集中最普通的类
    //记录路径与前一路径的相同部分
    for(i=1;i<Trip;i++)
     if(path_a[leaves][i]==0)
     {
                    path_a[leaves][i]=path_a[leaves-1][i];
     path_b[leaves][i]=path_b[leaves-1][i];
     }
            cout<<endl<<"IF ";
   for(i=1;i<Trip;i++)
    if(i==1)
     cout<<"a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
    else
     cout<<"^a["<<path_b[leaves][i]<<"]="<<path_a[leaves][i];
      
    //判断类别
    for(i=0,ll=0,lll=0;i<bn;i++)
    {
     if(b[i][0]==0)ll+=1;
     else lll+=1;
    }
    if(ll>lll)
    {
     cout<<"THEN class=0";
     path_a[leaves][0]=0;
    }
    else
    {
                    cout<<"THEN class=1";
     path_a[leaves][0]=1;
    }
            //修改树的深度
   if(path_a[leaves][Trip]==av[path_b[leaves][Trip]-1])
    for(i=Trip;i>1;i--)
     if(path_a[leaves][i]==av[path_b[leaves][i]-1])Trip-=1;
     else
                                        //去掉break;
             Trip-=1;
    leaves+=1;
    //未分类的样本集减少
             for(i=0,l=-1;i<=count;i++)
    {
     for(j=0,lll=0;j<bn;j++)
      if(s[i][M+1]==b[j][M+1])
       lll++;
         if(lll==0)
      {
       l+=1;
       for(ll=0;ll<M+2;ll++)
        a[l][ll]=s[l][ll];
      }
    }
       for(i=0,k=-1;i<l;i++)
    {
     k++;
     for(ll=0;ll<M+2;ll++)
                       s[k][ll]=a[l][ll];
    }
   count-=bn;
   }
            else//待分结点的样本集不为空时
   {
    //定义count_Positive记录属于正例的样本数
                int count_Positive=0;
    //p1,p2分别定义为正负例的样本数
    double p1,p2;
    double Entropy_Es;//Entropy_Es表示熵
    for(i=0;i<=count;i++)
     if(s[i][0]==1)
      count_Positive+=1;
    p1=double(count_Positive)/(count+1);
    p2=1-p1;
    Entropy_Es=-p1*log10(p1)/log10(2)-p2*log10(p2)/log10(2);
    cout<<p1<<'\t'<<p2<<'\t'<<Entropy_Es<<endl;
        //初始化
    
              for(i=0;i<sn;i++)//当前的属性包含的个数
      for(j=0;j<c;j++)//类别小类(每个属性包含的种类数)
       for(k=0;k<av[i];k++)
        ss[attribute_test_list[i]-1][j][k]=0;
                    //用数组ss[k][i][j]表示k个候选属性划分的子集sj中类ci的样本数,数组的具体大小可根据给定训练数据调整
       for(i=0;i<sn;i++)
        for(j=0;j<av[i];j++)
         count_s[attribute_test_list[i]-1][j]=0;//初始化某个属性的某个具体值的全部个数
       for(i=0;i<count+1;i++)
        for(j=1;j<=sn;j++)
         if(s[i][0]==0)
         {
          //找出每个属性具体某个值属于反例的个数
          ss[attribute_test_list[j-1]-1][0][s[i][j]-1]+=1;
          count_s[attribute_test_list[j-1]-1][s[i][j]-1]+=1;
         }
         else
         {
                                  ss[attribute_test_list[j-1]-1][1][s[i][j]-1]+=1;
          count_s[attribute_test_list[j-1]-1][s[i][j]-1]+=1;
         }
     //计算分别以各个候选属性划分样本后,各个子集sj中样本属于类ci的概率
        for(i=0;i<sn;i++)
         for(j=0;j<c;j++)
          for(k=0;k<av[i];k++)
           if(count_s[attribute_test_list[i]-1][k]!=0)
        p[attribute_test_list[i]-1][j][k]=double(ss[attribute_test_list[i]-1][j][k])/count_s[attribute_test_list[i]-1][k];

       for(i=0;i<sn;i++)
                          E[attribute_test_list[i]-1]=0.0;
       //计算熵
       for(i=0;i<sn;i++)
        for(j=0;j<av[attribute_test_list[i]-1];j++)
        {
                            //if语句处理0*log10(0)=0
         if(p[attribute_test_list[i]-1][0][j]==0||p[attribute_test_list[i]-1][1][j]==0)
         {
          p[attribute_test_list[i]-1][0][j]=1;
                                  p[attribute_test_list[i]-1][1][j]=1;
         }
                            E[attribute_test_list[i]-1]+=(ss[attribute_test_list[i]-1][0][j]+ss[attribute_test_list[i]-1][1][j])*(-(p[attribute_test_list[i]-1][0][j]*log10(p[attribute_test_list[i]-1][0][j])/log10(2)+p[attribute_test_list[i]-1][1][j]*log10(p[attribute_test_list[i]-1][1][j])/log10(2)))/(count+1);

        }

           //计算熵的信息增益
       for(i=0;i<sn;i++)
        Gain[attribute_test_list[i]-1]=Entropy_Es-E[attribute_test_list[i]-1];
       //找出信息增益的最大值,用j记录哪个候选属性的信息增益最大
       max_Gain=Gain[0];
                      j=attribute_test_list[0]-1;
       for(i=0;i<sn;i++)//找出最大的信息增益
        if(max_Gain<Gain[attribute_test_list[i]-1])
        {
                                max_Gain=Gain[attribute_test_list[i]-1];
                                j=attribute_test_list[i]-1;
        }
       //利用得到的具有最大信息增益的属性来划分待分的样本集b[bn][8]
        int temp[s_max];
        int b1[N][M+2];
        int temp1=-1;
        int temp_b[s_max][N][M+2];
                          for(i=1;i<=av[j];i++)
        {
         temp[i]=-1;
         for(k=0;k<bn;k++)//样本个数
          if(b[k][j+1]==i)
          {
           temp[i]+=1;
           for(l=0;l<M+2;l++)
            temp_b[i][temp[i]][l]=b[k][l];
          }
        }
     
        //对于每个分支使用递归函数重复生成树
        for(i=1;i<=av[j];i++)
        {
         for(k=0;k<=temp[i];k++)
                                  for(l=0;l<M+2;l++)
           b1[k][l]=temp_b[i][k][l];
          if(i==1)
          {
           for(ll=0,l=0;ll<sn;ll++)
            if(attribute_test_list[ll]-1!=j)attribute_test_list[l++]=attribute_test_list[ll];
            Generate_decision_tree(b1,k,attribute_test_list,l,i,j+1);
            sn-=1;
          }
          else
          {
           Generate_decision_tree(b1,k,attribute_test_list,sn,i,j+1);
           if(i==av[j])attribute_test_list[sn]=j+1;
          }
        }
   }

  }
 }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值