ID3 算法实现决策树

转自:http://www.cppblog.com/coreBugZJ/archive/2012/06/05/177654.html

ID3 算法实现决策树

  1 /*
  2
  3ID3 算法实现决策树
  4
  5
  6----问题描述:
  7
  8Suppose we want ID3 to decide whether the weather is amenable to playing baseball. Over the course of 2 weeks, data is collected to help ID3 build a decision tree (see table 1).
  9
 10The target classification is "should we play baseball?" which can be yes or no.
 11
 12The weather attributes are outlook, temperature, humidity, and wind speed. They can have the following values:
 13
 14•    outlook = { sunny, overcast, rain }
 15•    temperature = {hot, mild, cool }
 16•    humidity = { high, normal }
 17•    wind = {weak, strong }
 18
 19Examples of set S are:
 20
 21Table. 1
 22
 23Day    Outlook    Temperature    Humidity    Wind    Play ball
 24
 25D1    Sunny        Hot    High        Weak    No
 26D2    Sunny        Hot    High        Strong    No
 27D3    Overcast    Hot    High        Weak    Yes
 28D4    Rain        Mild    High        Weak    Yes
 29D5    Rain        Cool    Normal        Weak    Yes
 30D6    Rain        Cool    Normal        Strong    No
 31D7    Overcast    Cool    Normal        Strong    Yes
 32D8    Sunny        Mild    High        Weak    No
 33D9    Sunny        Cool    Normal        Weak    Yes
 34D10    Rain        Mild    Normal        Weak    Yes
 35D11    Sunny        Mild    Normal        Strong    Yes
 36D12    Overcast    Mild    High        Strong    Yes
 37D13    Overcast    Hot    Normal        Weak    Yes
 38D14    Rain        Mild    High        Strong    No
 39
 40
 41----输入:
 42
 43若干行,每行 5 个字符串,表示
 44
 45Outlook    Temperature    Humidity    Wind    Play ball
 46
 47如上表。
 48
 49
 50----输出:
 51
 52决策树。
 53
 54
 55----分析:
 56
 57经典 ID3 算法。
 58
 59代码假设训练集相容。
 60
 61非常经典的算法,第一次实现,如此仓促以至于得到如此恶心的代码!
 62我所写过的最恶心的代码!真想删了重新写。
 63
 64*/

 65
 66
 67 #include  < iostream >
 68 #include  < cstdio >
 69 #include  < string >
 70 #include  < map >
 71 #include  < iomanip >
 72 #include  < cmath >
 73
 74 using   namespace  std;
 75
 76 const   int  EXAMPLE_NUM   =   1009 ;
 77 const   int  PROP_NUM      =   4 ;
 78
 79 const   int  MAX_PROP[ PROP_NUM ]  =   3322 } ;
 80
 81 struct   Example
 82 {
 83        int  prop[ PROP_NUM ];
 84        bool ignp[ PROP_NUM ];
 85        bool play;
 86
 87        int  node;
 88        Example *link;
 89}
;
 90
 91 struct   Node;
 92
 93 struct   Link
 94 {
 95        int   prop;
 96        Node  *node;
 97        Link  *link;
 98}
;
 99
100 struct   Node
101 {
102        int   pid;
103        Link  *link;
104        bool  play;
105}
;
106
107 map <   string int   >  Str2Val;
108 map <   int string   >  Val2Str[ PROP_NUM ];
109 string   Pro2Str[ PROP_NUM ]  =   "Outlook""Temperature""Humidity""Wind" } ;
110
111
112 double   entropy( Example  * s,  int  nd,  int   & ts )  {
113        int ct = 0, cf = 0, c = 0;
114        double es = 0;
115        while ( NULL != s ) {
116                if ( nd == s->node ) {
117                        ++c;
118                        if ( s->play ) {
119                                ++ct;
120                        }

121                        else {
122                                ++cf;
123                        }

124                }

125                s = s->link;
126        }

127        ts = c;
128        if ( 0 == c ) {
129                return 0;
130        }

131        if ( 0 != ct ) {
132                es += -(((double)(ct))/c) * log(((double)(ct))/c);
133        }

134        if ( 0 != cf ) {
135                es += -(((double)(cf))/c) * log(((double)(cf))/c);
136        }

137        return es;
138}

139          //  pid 合法
140 double  gain( Example  * s,  int  nd,  int  pid )  {
141        Example *e;
142        double  es, ev;
143        int     ts, tv, i;
144
145        es = entropy( s, nd, ts );
146
147        if ( 0 == ts ) {
148                return 0;
149        }

150
151        for ( i = 0; i < MAX_PROP[ pid ]; ++i ) {
152                for ( e = s; NULL != e; e = e->link ) {
153                        if ( (nd == e->node) && (i == e->prop[pid]) && (! e->ignp[pid]) ) {
154                                e->node = nd + 1;
155                        }

156                }

157
158                ev = entropy( s, nd+1, tv );
159
160                for ( e = s; NULL != e; e = e->link ) {
161                        if ( nd+1 == e->node ) {
162                                e->node = nd;
163                        }

164                }

165
166                es -= ev * ( ((double)(tv)) / ts );
167        }

168
169        return es;
170}

171
172 int  gainMaxId( Example  * s,  int  nd )  {
173        double m = -1e100, tm;
174        int    k = -1, i;
175        bool   ign[ PROP_NUM ] = 0 };
176
177        for ( Example *= s; NULL != e; e = e->link ) {
178                if ( e->node == nd ) {
179                        for ( i = 0; i < PROP_NUM; ++i ) {
180                                if ( e->ignp[ i ] ) {
181                                        ign[ i ] = true;
182                                }

183                        }

184                }

185        }

186
187        for ( i = 0; i < PROP_NUM; ++i ) {
188                if ( ign[ i ] ) {
189                        continue;
190                }

191
192                tm = gain( s, nd, i );
193                if ( tm > m ) {
194                        m = tm;
195                        k = i;
196                }

197        }

198
199        return k;
200}

201          //  s 非空
202 bool  sameDecd( Example  * s,  int  nd,  bool   & decd )  {
203        bool set = false;
204        bool play;
205        while ( NULL != s ) {
206                if ( s->node == nd ) {
207                        play = s->play;
208                        set  = true;
209                        break;
210                }

211                s = s->link;
212        }

213        if ( ! set ) {
214                return false////////
215        }

216        while ( NULL != s ) {
217                if ( (s->node == nd) && (s->play != play) ) {
218                        return false;
219                }

220                s = s->link;
221        }

222        decd = play;
223        return true;
224}

225          //  用完所有属性
226 bool  isLeaf( Example  * s,  int  nd,  bool   & decd )  {
227        int i;
228        while ( NULL != s ) {
229                if ( s->node == nd ) {
230                        for ( i = 0; (i < PROP_NUM)&&(s->ignp[i]); ++i ) {
231                        }

232                        if ( i < PROP_NUM ) {
233                                return false;
234                        }

235                        decd = s->play;
236                }

237                s = s->link;
238        }

239        return true;
240}

241
242 int  node;
243 Node *  createTreeSub( Example  * example )  {
244        Node *res = new Node;
245        res->link = NULL;
246        res->pid = -1;
247        if ( sameDecd( example, node, res->play ) ) {
248                return res;
249        }

250        if ( isLeaf( example, node, res->play ) ) {
251                return res;
252        }

253
254        res->pid = gainMaxId( example, node );
255
256        int i, c, nd = node;
257        Example *e;
258        for ( i = 0; i < MAX_PROP[ res->pid ]; ++i ) {
259                e = example;
260                c = 0;
261                ++node;
262                while ( NULL != e ) {
263                        if ( (nd == e->node) && (i == e->prop[ res->pid ]) ) {
264                                e->ignp[ res->pid ] = true;
265                                e->node = node;
266                                ++c;
267                        }

268                        e = e->link;
269                }

270                if ( 0 < c ) {
271                        Link *link = new Link;
272                        link->node = createTreeSub( example );
273                        link->prop = i;
274                        link->link = res->link;
275                        res->link  = link;
276                }

277        }

278
279        return res;
280}

281
282 Node *  createTree( Example *  example )  {
283        Example *ptr;
284        int i;
285
286        if ( NULL == example ) {
287                return NULL;
288        }

289
290        for ( ptr = example; NULL != ptr; ptr = ptr->link ) {
291                for ( i = 0; i < PROP_NUM; ++i ) {
292                        ptr->ignp[ i ] = false;
293                }

294                ptr->node = 0;
295        }

296        node = 0;
297        return createTreeSub( example );
298}

299
300 void  outputTreeSub( Node  * tree,  int  dep );
301
302 void  outputLink( Link  * link,  int  dep,  int  pid )  {
303        if ( (NULL == link) || (0 > dep) ) {
304                return;
305        }

306
307        for ( int i = 0; i < dep; ++i ) {
308                cout << setw(16<< " ";
309        }

310        cout << left << setw(16<< Val2Str[pid][link->prop];
311        outputTreeSub( link->node, dep+1 );
312
313        outputLink( link->link, dep, pid );
314}

315
316 void  outputTreeSub( Node  * tree,  int  dep )  {
317        if ( (NULL == tree) || (0 > dep) ) {
318                return;
319        }

320
321        if ( 0 > tree->pid ) {
322                cout << (tree->play ? "Yes *" : "No  *"<< endl;
323                return;
324        }

325
326        cout << left << setw(16<< Pro2Str[tree->pid] << endl;
327        outputLink( tree->link, dep+1, tree->pid );
328}

329
330 void  outputTree( Node  * tree )  {
331        outputTreeSub( tree, 0 );
332}

333
334 void  destroyTree( Node  ** pTree )  {
335        if ( (NULL == pTree) || (NULL == *pTree) ) {
336                return;
337        }

338
339        Link *link;
340        for ( link = (*pTree)->link; NULL != link; link = link->link ) {
341                destroyTree( &(link->node) );
342        }

343
344        delete *pTree;
345        *pTree = NULL;
346}

347
348 void  destroyExample( Example  ** pExample )  {
349        if ( (NULL == pExample) || (NULL == *pExample) ) {
350                return;
351        }

352        Example  *head = *pExample, *p;
353        while ( NULL != head ) {
354                p = head;
355                head = head->link;
356                delete p;
357        }

358        *pExample = NULL;
359}

360
361 void  init()  {
362        Val2Str[ 0 ][ 0 ] = "Sunny";
363        Val2Str[ 0 ][ 1 ] = "Overcast";
364        Val2Str[ 0 ][ 2 ] = "Rain";
365        Str2Val[ "Sunny"    ] = 0;
366        Str2Val[ "Overcast" ] = 1;
367        Str2Val[ "Rain"     ] = 2;
368        
369        Val2Str[ 1 ][ 0 ] = "Hot";
370        Val2Str[ 1 ][ 1 ] = "Mild";
371        Val2Str[ 1 ][ 2 ] = "Cool";
372        Str2Val[ "Hot"  ] = 0;
373        Str2Val[ "Mild" ] = 1;
374        Str2Val[ "Cool" ] = 2;
375
376        Val2Str[ 2 ][ 0 ] = "High";
377        Val2Str[ 2 ][ 1 ] = "Normal";
378        Str2Val[ "High"   ] = 0;
379        Str2Val[ "Normal" ] = 1;
380
381        Val2Str[ 3 ][ 0 ] = "Weak";
382        Val2Str[ 3 ][ 1 ] = "Strong";
383        Str2Val[ "Weak"   ] = 0;
384        Str2Val[ "Strong" ] = 1;
385}

386
387 Example *   inputExample()  {
388        Example   *preHead = new Example;
389        Example   *ptr;
390        string    Outlook, Temperature, Humidity, Wind, Play;
391
392        preHead->link = NULL;
393        ptr = preHead;
394
395        while ( cin >> Outlook >> Temperature >> Humidity >> Wind >> Play ) {
396                ptr->link = new Example;
397                ptr = ptr->link;
398                ptr->link = NULL;
399
400                if (    (Str2Val.find( Outlook     ) == Str2Val.end()) || 
401                        (Str2Val.find( Temperature ) == Str2Val.end()) || 
402                        (Str2Val.find( Humidity    ) == Str2Val.end()) || 
403                        (Str2Val.find( Wind        ) == Str2Val.end()) 
404                        ) {
405                                destroyExample( &preHead );
406                                return NULL;
407                }

408                ptr->prop[ 0 ] = Str2Val[ Outlook     ];
409                ptr->prop[ 1 ] = Str2Val[ Temperature ];
410                ptr->prop[ 2 ] = Str2Val[ Humidity    ];
411                ptr->prop[ 3 ] = Str2Val[ Wind        ];
412
413                if ( "Yes" == Play ) {
414                        ptr->play = true;
415                }

416                else if ( "No" == Play ) {
417                        ptr->play = false;
418                }

419                else {
420                        destroyExample( &preHead );
421                        return NULL;
422                }

423        }

424
425        ptr = preHead->link;
426        delete preHead;
427        return ptr;
428}

429
430 int  main()  {
431        init();
432
433        Example  *example = inputExample();
434        if ( NULL == example ) {
435                cout << "输入不合法" << endl;
436                return 0;
437        }

438
439        Node  *tree = createTree( example );
440
441        outputTree( tree );
442
443        destroyTree( &tree );
444        destroyExample( &example );
445        return 0;
446}

447
448
449 /*
450
451输入:
452    Sunny        Hot    High        Weak    No
453    Sunny        Hot    High        Strong    No
454    Overcast    Hot    High        Weak    Yes
455    Rain        Mild    High        Weak    Yes
456    Rain        Cool    Normal        Weak    Yes
457    Rain        Cool    Normal        Strong    No
458    Overcast    Cool    Normal        Strong    Yes
459    Sunny        Mild    High        Weak    No
460    Sunny        Cool    Normal        Weak    Yes
461    Rain        Mild    Normal        Weak    Yes
462    Sunny        Mild    Normal        Strong    Yes
463    Overcast    Mild    High        Strong    Yes
464    Overcast    Hot    Normal        Weak    Yes
465    Rain        Mild    High        Strong    No
466
467输出:
468
469Outlook
470                Rain            Wind
471                                                Strong          No  *
472                                                Weak            Yes *
473                Overcast        Yes *
474                Sunny           Humidity
475                                                Normal          Yes *
476                                                High            No  *
477
478*/

479

你可能感兴趣的:(ID3 算法实现决策树)