周志华《机器学习》 ID3实现雏形(未完善,未运行)

博主分享了自己阅读机器学习中决策树部分后尝试实现ID3算法的过程,目前实现处于雏形阶段,尚未完成样例运行和实例化。

最近阅读机器学习的决策树,突发奇想写了一下ID3实现,未完待续,保存下来等有时间接着写,大体框架是这样

目前还未写样例运行,未实例化

实现指导如下:

#include <iostream>
#include <string>
#include <decisionTree.h>

using namespace std;

int main()
{
  AA attr;
  DD sample;
  decisionTree *m=new decisionTree();
  NODE *root;
  m->TreeGenerate(sample,attr,root);


}



#ifndef DECISIONTREE_H
#define DECISIONTREE_H
#define MAX 10000
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;


struct  A{
    int id;       //属性ID
    string name;  //属性名字
    int value;    //属性值
};

struct AA
{
    int a_num;     //属性集的大小
    vector<A> aa;  //属性集
    vector<bool> canUse;
};

struct  D       //(xi,yi)
{

    int x_num;  //  属性X的长度
    int y_num;  //  y的类别个数
    vector<A> x;// xi向量值
    int y;      // yi值
};
struct DD     //样本集
{
    int d_num;
    vector<D> dd;
};
struct re_A{        //返回属性值信息
   int id;
   string name;
   int value_num;   //属性值的个数
   vector<int> values ; //所有属性值


};
struct NODE
{


    int type;       //0是root,1是中节点,2是叶节点
    int CLASS;      //分类类别,同Y
    vector <NODE*> child;
    int child_num;  //子节点数
    re_A attribute;    //节点分类属性

};

class decisionTree
{
    public:
        decisionTree();
        virtual ~decisionTree();
        void TreeGenerate(DD d,AA a,NODE *node);
        bool allSameType(DD d);  //样本是否都属于一个类
        bool allSameinA(DD d);   //样本是否在属性集上相同,不可分
        int mostClass(DD d);     //样本集属于最多的类别
        re_A findBestA(DD d, AA a);
        DD findD_inA(DD d,A a);
        double Ent(DD d);
        double Gain(DD d,re_A a);
        re_A find_reA(DD d,A a);
    protected:

    private:
};

#endif // DECISIONTREE_H

#include "decisionTree.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <memory>
#include <math.h>
#include <set>
using namespace std;
decisionTree::decisionTree()
{
    //ctor
}

decisionTree::~decisionTree()
{
    //dtor
}
double decisionTree::Ent(DD d)
{
    int re[MAX];
    memset(re,0,sizeof(re));
    for(int i=1;i<=d.d_num;i++)
    {
        re[d.dd[i].y]++;
    }
    double sum=0.0;
    for(int i=1;i<=d.dd[0].y_num;i++)
    {
        double a=1.0*re[i]/d.d_num;
        sum+=log(a)/log(2)*a;
    }
    sum=-1*sum;
    return sum;
}
double decisionTree::Gain(DD d,re_A a)  //在一个属性a上的信息增益
{
    double re[MAX];
    double all=0.0;
    int num[MAX];
    memset(re,0.0,sizeof(re));
    memset(num,0,sizeof(num));
    for(int i=1;i<=a.value_num;i++)
    {
        A aa;
        aa.id=a.id;
        aa.name=a.name;
        aa.value=a.values[i];
        DD sd;
        sd=findD_inA(d,aa);
        num[i]=sd.d_num;
        re[i]=Ent(sd);
        all=all-num[i]/d.d_num*re[i];
    }
    re[0]=Ent(d);
    all+=re[0];
    return all;

}
bool decisionTree::allSameType(DD d)
{
    for(int i=0;i<d.d_num;i++)
    {
        if(d.dd[i].y!=d.dd[0].y)
            return false;
    }
    return true;
}
bool decisionTree::allSameinA(DD d)
{
    for(int i=0;i<d.dd[0].x_num;i++)  //对所有属性
      for(int j=0;j<d.d_num;j++)   //对每个属性上的样例
      {
          if(d.dd[j].x[i].value!=d.dd[0].x[i].value)
            return false;
      }

}
int decisionTree::mostClass(DD d)
{
    int result[MAX],cla;
    memset(result,0,sizeof(result));
    result[0]=-1;
    for(int i=0;i<d.d_num;i++)
        result[d.dd[i].y]++;
    for(int i=1;i<=d.dd[0].y_num;i++)
    {
        if(result[i]>result[i-1])
            cla=i; //最多的类
    }
    return cla;
}
re_A decisionTree::find_reA(DD d,A a)
{

   set<int> s;
   for(int i=1;i<=d.d_num;i++)
   {
       s.insert(d.dd[i].x[a.id].value);
   }
   re_A c;
   c.value_num=s.size();
   c.id=a.id;
   c.name=a.name;
   set<int>::reverse_iterator rit;
   for(rit=s.rbegin();rit!=s.rend();rit++)
   {
       c.values.push_back(*rit);
   }

}
re_A decisionTree::findBestA(DD d, AA a)
{
    double ga[MAX];
    memset(ga,-1.0,sizeof(ga));
    for(int i=1;i<=a.a_num;i++)
    {
        if(a.canUse[i])
        {
            re_A each=find_reA(d,a.aa[i]);
            ga[i]=Gain(d,each);
        }
    }
    double best=-10;
    int id=-1;
    for(int i=1;i<=a.a_num;i++)
    {
        if(ga[i]>best)
        {
            best=ga[i];
            id=i;
        }
    }
    re_A be;
    be=find_reA(d,a.aa[id]);
    return be;
}
DD decisionTree::findD_inA(DD d,A a)
{
     DD subD;
     int s=0;
     for(int i=1;i<=d.d_num;i++)
     {
         if(d.dd[i].x[a.id].value==a.value)
            {
                s++;
                subD.dd.push_back(d.dd[i]);
            }
     }
     subD.d_num=s;
     return subD;
}
void decisionTree::TreeGenerate(DD d, AA a, NODE *node)
{

   if (allSameType(d))
   {
       node->type=3;  //叶节点
       node->CLASS=d.dd[0].y;
       //node->sample=d;
       return ;
   }
   else if(a.a_num==0||allSameinA(d))
   {
       node->type=3;
       node->CLASS=mostClass(d);
       //node->sample=d;
       return ;
   }
   else
   {
       re_A best_a;
       best_a=findBestA(d,a);
       node->attribute=best_a;
       for(int i=1;i<=best_a.value_num;i++)
       {
           NODE* c_node;
           node->child_num ++;
           node->child.push_back(c_node);
           A c_a;
           c_a.id=best_a.id;
           c_a.name=best_a.name;
           c_a.value=best_a.values[i];
           DD c_d;
           c_d=findD_inA(d,c_a);
           if(c_d.d_num=0)
           {
               node->child[node->child_num]->type=3;
               node->child[node->child_num]->CLASS=mostClass(d);

               //node->sample=d;
               return ;
           }
           else{
            a.canUse[best_a.id]=false; //去除a中使用的属性
            TreeGenerate(c_d,a,node->child[node->child_num]);
           }

       }
   }
}

以下是朴素贝叶斯分类器的伪代码: 1. 训练阶段: (1)对于每个类别 i,计算先验概率P(Y=i)。 (2)对于每个特征 j,计算在每个类别 i 下该特征的条件概率P(Xj=x|Y=i)。 2. 测试阶段: (1)对于输入样本 x,计算该样本属于每个类别 i 的条件概率P(Y=i|X=x)。 (2)将样本分到概率最大的类别中。 下面是朴素贝叶斯分类器的 C++ 代码实现,其中假设特征和类别都是离散的: ``` #include <iostream> #include <vector> #include <map> #include <cmath> using namespace std; // 计算先验概率 map<int, double> cal_prior_prob(vector<int>& labels) { map<int, double> prior_prob; int total = labels.size(); for (int i = 0; i < total; i++) { int label = labels[i]; if (prior_prob.find(label) == prior_prob.end()) { prior_prob[label] = 0.0; } prior_prob[label] += 1.0; } for (auto iter = prior_prob.begin(); iter != prior_prob.end(); iter++) { iter->second /= total; } return prior_prob; } // 计算条件概率 map<int, map<int, double>> cal_cond_prob(vector<vector<int>>& features, vector<int>& labels) { map<int, map<int, double>> cond_prob; int total = labels.size(); int feature_num = features[0].size(); for (int i = 0; i < total; i++) { int label = labels[i]; if (cond_prob.find(label) == cond_prob.end()) { cond_prob[label] = map<int, double>(); } for (int j = 0; j < feature_num; j++) { int feature = features[i][j]; if (cond_prob[label].find(j) == cond_prob[label].end()) { cond_prob[label][j] = map<int, double>(); } if (cond_prob[label][j].find(feature) == cond_prob[label][j].end()) { cond_prob[label][j][feature] = 0.0; } cond_prob[label][j][feature] += 1.0; } } for (auto iter1 = cond_prob.begin(); iter1 != cond_prob.end(); iter1++) { int label = iter1->first; for (auto iter2 = iter1->second.begin(); iter2 != iter1->second.end(); iter2++) { int feature = iter2->first; int feature_total = iter2->second.size(); for (auto iter3 = iter2->second.begin(); iter3 != iter2->second.end(); iter3++) { iter3->second /= feature_total; } } } return cond_prob; } // 预测 int predict(vector<int>& feature, map<int, double>& prior_prob, map<int, map<int, double>>& cond_prob) { int label = -1; double max_prob = -1.0; for (auto iter = prior_prob.begin(); iter != prior_prob.end(); iter++) { int cur_label = iter->first; double cur_prob = log(iter->second); for (int i = 0; i < feature.size(); i++) { cur_prob += log(cond_prob[cur_label][i][feature[i]]); } if (cur_prob > max_prob) { max_prob = cur_prob; label = cur_label; } } return label; } // 测试 void test(vector<vector<int>>& features, vector<int>& labels, map<int, double>& prior_prob, map<int, map<int, double>>& cond_prob) { int total = labels.size(); int correct = 0; for (int i = 0; i < total; i++) { int predict_label = predict(features[i], prior_prob, cond_prob); if (predict_label == labels[i]) { correct++; } } cout << "Accuracy: " << (double)correct / total << endl; } int main() { // 读取数据,features存放特征,labels存放类别 vector<vector<int>> features; vector<int> labels; // 训练 map<int, double> prior_prob = cal_prior_prob(labels); map<int, map<int, double>> cond_prob = cal_cond_prob(features, labels); // 测试 test(features, labels, prior_prob, cond_prob); return 0; } ``` 注意:这里的代码只是朴素贝叶斯分类器的一种实现方式,可能还有其他实现方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值