数据挖掘实验:决策树算法实现C++

来源:互联网 发布:广州电脑数据恢复 编辑:程序博客网 时间:2024/04/28 12:44

决策树算法看起来很好玩(我没开玩笑我真的这么觉得),就是简单的树上走然后得到不同的结果,一开始我很纳闷,书上那些东西都是啥,什么信息增益,ID3,C4.5,都是什么玩意(不好好听课的后果),后来仔仔细细的把书看了三遍,终于明白是干嘛的了。其实是根据给出的数据,判断不同属性对于决策的贡献,然后获得这棵树的分支。理解之后实现起来就容易一些了,实现的时候也借鉴了别人的代码,研究透了之后自己写的,同时也做了一些改动,数组没有用指针(我不喜欢指针),用的数组+下标寻址。然后,这代码你要是让我再写一遍我告诉你,


我肯定写不出来。


当时写了有六七个小时呢(还是弄懂了别人代码的前提下,光看书实在不懂到底想干嘛)。

#include <cstdio>#include <iostream>#include <string>#include <map>#include <set>#include <vector>#include <cmath>#include <cstring>using namespace std;const int maxn = 10005;struct P {    string name;    string val;    int id;    vector<int> son;    P():id(-1){}}Tree[maxn];int n;///元组数int m;///数据条数int tot;///节点总数int root;///根节点idvector<vector<string> > dataset;///所有数据vector<string > col_name;///列名map<string, vector<string> > Map;///存储属性对应的值int nump[10];///用于标号///判断是否是同一类bool All(vector<vector<string> > D, string kind){    for(int i = 0;i < D.size();i ++)        if(D[i][n - 1] != kind) return false;    return true;}///取多数类的属性string Most(vector<vector<string> > D){    int num = 0;    for(int i = 0;i < D.size();i ++)        if(D[i][n - 1] == "yes") num ++;    return (num > D.size() - num)?"yes":"no";}///计算Infodouble Cal_Info(vector <vector <string> > D, string attribute, string value,bool first){    int t1 = 0, t2 = 0;    bool flag = false;    for(int j = 0; j < n; j ++){        if(flag) break;        if(col_name[j] == attribute){            for(int i = 0; i < D.size(); i++)                if((!first&&D[i][j] == value) || first){                    if(D[i][n - 1] == "yes") t1++;                    else t2++;                }            flag = true;        }    }    ///属于同一类    if(t1 == 0 || t2 == 0 ) return 0;    double sum = t1 + t2;    double ans = -t1/sum*log(t1/sum)/log(2.0) - t2/sum*log(t2/sum)/log(2.0);    return ans;}///计算信息增益double Cal_Gain(vector <vector <string> > D, string attribute){    double Info = Cal_Info(D, attribute, "", true);    double InfoA = 0;    vector<string> v = Map[attribute];    vector<double> ans;    vector<int> vv;    int t1;    for(int i = 0; i < v.size(); i++){        t1 = 0;        for(int k = 0; k < n - 1; k++)            if(col_name[k] == attribute){                for(int j = 0; j < D.size(); j++)                    if(D[j][k] == v[i])                        t1 ++;            }        vv.push_back(t1);    }    for(int i = 0; i < v.size();i ++)        ans.push_back(1.0 * vv[i] / (D.size()));    double temp;    for(int i = 0; i < v.size();i ++){        temp = Cal_Info(D, attribute, v[i], false);        InfoA += ans[i] * temp;    }    return (Info - InfoA);}///建树过程int Generate_decision_tree(int pos, vector<vector<string> > D, vector <string> attribute_list){    if(Tree[pos].id == -1) Tree[pos].id = pos;    ///所有数据结果都是yes    if(All(D, "yes")){        Tree[pos].name = "yes";        return pos;    }///所有数据结果都是no    else if(All(D, "no")){        Tree[pos].name = "no";        return pos;    }    ///属性判断完毕仍不能分开,取多数    if(attribute_list.size() == 0){        Tree[pos].name = Most(D);        return pos;    }    ///计算最大增益    double maxg = -1;    int maxpos = 0;    for(int i = 0;i < attribute_list.size();i ++){        double curg = Cal_Gain(D, attribute_list[i]);        if(curg > maxg){            maxg = curg;            maxpos = i;        }    }    ///根据最大增益对应的属性进行划分    Tree[pos].name = attribute_list[maxpos];    ///获得属性对应的所有值    vector<string> v = Map[attribute_list[maxpos]];    int p;    for(p = 0;p < n;p ++)    if(col_name[p] == attribute_list[maxpos])        break;    vector<string> tempatt;    vector<vector<string > > tempD;    for(int i = 0;i < attribute_list.size();i ++)        if(i != maxpos) tempatt.push_back(attribute_list[i]);    for(int i = 0;i < v.size();i ++){        for(int j = 0;j < D.size();j ++)            if(D[j][p] == v[i])                tempD.push_back(D[j]);        int curnum = ++ tot ;        Tree[curnum].val = v[i];        if(tempD.size() == 0) Tree[curnum].name = Most(D);        else Generate_decision_tree(curnum, tempD, tempatt);        Tree[pos].son.push_back(curnum);        tempD.clear();    }    return pos;}///遍历void show(int id, int dep){    for(int i = 0;i < dep;i ++) cout<<"   ";    if(Tree[id].val != ""){        dep ++;        cout<<++ nump[dep]<<"."<<Tree[id].val<<endl;        for(int i = 0;i < dep;i++)            cout<<"   ";    }    cout<<Tree[id].name<<endl;    for(int i = 0;i < Tree[id].son.size();i++){        show(Tree[id].son[i], dep+1);    }}int main(){    freopen("1.txt", "r", stdin);    memset(nump, 0, sizeof nump);    string t;    vector<string > data;    cin >> n >> m;    for(int i = 0;i < n;i ++)        cin >> t, col_name.push_back(t);    for(int i = 0;i < m;i ++){        data.clear();        for(int j = 0;j < n;j ++){            cin >> t;            data.push_back(t);        }        dataset.push_back(data);    }    ///获得每个属性对应的值    vector<string> vt;    set<string> ss;    for(int i = 0;i < n - 1;i ++){        vt.clear();        ss.clear();        for(int j = 0;j < m;j ++)            if(!ss.count(dataset[j][i])){                ss.insert(dataset[j][i]);                vt.push_back(dataset[j][i]);            }        Map[col_name[i]] = vt;    }    vt = col_name;    vt.erase(vt.end() - 1);    root = Generate_decision_tree(0, dataset, vt);    show(root,0);    return 0;}
然后输入数据的话我就不附了,就是列数 记录条数,酱,主题的递归算法,过程跟书上是一样的。哦对了,我的书是机械工业出版社的数据挖掘,黑色大理石纹,我觉得还不错。起码我从书上还真学到了点啥(虽然后期忙着复习没有好好听课)。



原创粉丝点击