决策树ID3算法[分类算法]
ID3分类算法的编码实现
1 <?php 2 /* 3 *决策树ID3算法(分类算法的实现) 4 */ 5 6 7 8 /* 9 10 *求信息增益Grain(S1,S2) 11 12 */ 13 14 //-------------------------------------------------------------------- 15 function Grain($train,$attriname,$flagsyes,$flagsno) 16 { 17 $attributename = array(NULL);//用来存放属性$attriname不同的属性值 18 array_splice($attributename,0,1); 19 20 for($i=1;$i<count($train[0]);$i++) 21 { 22 if($attriname==$train[0][$i]) 23 { 24 $num = $i;//记录$train第几个属性是$attriname 25 for($j=1;$j<count($train);$j++) 26 { 27 $flags = true;//用于判断将要存放的属性值是否已经存在 28 for($k=0;$k<count($attributename);$k++) 29 { 30 if($attributename[$k]==$train[$j][$i])//即将存入的属性值已经存在 31 { 32 $flags = false; 33 break; 34 } 35 } 36 if($flags)//新的属性值不存在,$attributename存入新的属性值 37 { 38 array_push($attributename,$train[$j][$i]); 39 } 40 } 41 break; 42 } 43 } 44 45 for($i=0;$i<count($attributename);$i++) 46 { 47 $count[$i][0] = $attributename[$i];//属性名称 48 $count[$i][1] = 0;//用来统计$attributename[$i] $flagsyes的个数 49 $count[$i][2] = 0;//用来统计$attributename[$i] $flagsno的个数 50 } 51 52 for($i=1;$i<count($train);$i++) 53 { 54 for($j=0;$j<count($attributename);$j++) 55 { 56 //print_r($train[$i][count($train[$i])-1]."<br>"); 57 if(($train[$i][$num]==$attributename[$j])&&($train[$i][count($train[$i])-1]==$flagsyes)) 58 { 59 $count[$j][1]++; 60 }else if(($train[$i][$num]==$attributename[$j])&&($train[$i][count($train[$i])-1]==$flagsno)){ 61 $count[$j][2]++; 62 } 63 } 64 } 65 66 $num_yes = 0;//类别为$flagsyes的个数 67 $num_no = 0;//类别为$flagsno的个数 68 for($i=1;$i<count($train);$i++) 69 { 70 if($train[$i][count($train[$i])-1]==$flagsyes) 71 { 72 $num_yes++; 73 }else { 74 $num_no++; 75 } 76 } 77 78 //分类所需要的 信息量 79 $I=0; 80 $s[0] = $num_yes; 81 $s[1] = $num_no ; 82 for($i=0;$i<2;$i++) 83 { 84 if($s[$i]!=0)$I += -$s[$i] / ($num_yes+$num_no) * log($s[$i]/($num_yes+$num_no)) / log(2); 85 } 86 87 $EA = 0 ; 88 for($i=0;$i<count($count);$i++) 89 { 90 $si = 0; 91 for($j=1;$j<count($count[$i]);$j++) 92 { 93 if($count[$i][$j]!=0)$si += -$count[$i][$j] / ($count[$i][1]+$count[$i][2]) * log($count[$i][$j]/($count[$i][1]+$count[$i][2])) / log(2); 94 } 95 $EA += ($count[$i][1]+$count[$i][2])/($num_yes+$num_no) * $si; 96 } 97 98 //信息增益Gain 99 $Gain = $I - $EA; 100 return $Gain; 101 } 102 //-------------------------------------------------------------------- 103 104 /* 105 106 *求几个属性信息增益最大的那一个 107 108 */ 109 110 //-------------------------------------------------------------------- 111 function Attributelist($train,$flagsyes,$flagsno) 112 { 113 $array_attribute_grain = array(array(NULL,NULL));//存放属性值以及属性值对应的信息增益 114 for($i=1;$i<count($train[0])-1;$i++) 115 { 116 $array_attribute_grain[$i-1][0] = $train[0][$i]; 117 $array_attribute_grain[$i-1][1] = Grain($train,$train[0][$i],$flagsyes,$flagsno); 118 } 119 120 for($i=1;$i<count($array_attribute_grain);$i++) 121 { 122 if($array_attribute_grain[$i][1]>$array_attribute_grain[0][1]) 123 { 124 $array_attribute_grain[0][0] = $array_attribute_grain[$i][0]; 125 $array_attribute_grain[0][1] = $array_attribute_grain[$i][1]; 126 } 127 128 } 129 /* 130 echo "<pre>"; 131 print_r($array_attribute_grain[0]); 132 echo "<pre>"; 133 */ 134 return $array_attribute_grain[0]; 135 } 136 //-------------------------------------------------------------------- 137 138 /* 139 140 *构建ID3决策树(数组存储) 141 142 */ 143 144 //-------------------------------------------------------------------- 145 function DecisionTree($train,$flagsyes,$flagsno,&$array_tree) 146 { 147 $flags = true; 148 /* 149 *if所有样本均为同一类别C,返回N作为一个椰子结点并标志为C类别 150 */ 151 $num_yes = 0;//用于统计同一$flagsyes类别的数目 152 $num_no = 0;//用于统计同一$flagsno类别的数目 153 for($i=1;$i<count($train);$i++) 154 { 155 if($train[$i][count($train[$i])-1]==$flagsyes) $num_yes++; 156 else if($train[$i][count($train[$i])-1]==$flagsno) $num_no++; 157 } 158 159 160 if($num_yes==(count($train)-1))//所有样本均为同一类别 161 { 162 array_push($array_tree,array($flagsyes)); 163 $count++; 164 $flags = false; 165 }else if($num_no==(count($train)-1)){ 166 array_push($array_tree,array($flagsno)); 167 $count++; 168 $flags = false; 169 } 170 171 172 /* 173 174 *else if attribute /为空,则返回n作为一个叶子节点,并标记为该节点所含样本中类别最多的类别 175 176 */ 177 if($flags) 178 { 179 $num_attribute = count($train)-2; 180 if($num_attribute==0) 181 { 182 if($num_yes>$num_no) 183 { 184 array_push($array_tree,array($flagsyes)); 185 $count++; 186 $flags = false; 187 }else { 188 array_push($array_tree,array($flagsno)); 189 $count++; 190 $flags = false; 191 } 192 193 } 194 } 195 /* 196 197 *从样本中选择分类能力最好的的属性 198 199 */ 200 if($flags) 201 { 202 $attribute = Attributelist($train,$flagsyes,$flagsno); 203 204 $attribute_name = array(NULL); 205 array_splice($attribute_name,0,1); 206 for($i=1;$i<count($train[0])-1;$i++) 207 { 208 if($train[0][$i]==$attribute[0]) 209 { 210 $num = $i; 211 break; 212 } 213 } 214 for($i=1;$i<count($train);$i++) 215 { 216 $flags2 = true; 217 for($j=0;$j<count($attribute_name);$j++) 218 { 219 if($train[$i][$num]==$attribute_name[$j]) 220 { 221 $flags2 = false; 222 break; 223 } 224 } 225 if($flags2)array_push($attribute_name,$train[$i][$num]); 226 } 227 //print_r($attribute_name); 228 $array_new = array(NULL); 229 array_splice($array_new,0,1); 230 for($i=0;$i<count($attribute_name);$i++) 231 { 232 $arraybranch = array(array()); 233 array_splice($arraybranch,0,1); 234 $arraytemp = array(NULL); 235 array_splice($arraytemp,0,1); 236 array_push($arraybranch,$train[0]); 237 for($j=1;$j<count($train);$j++) 238 { 239 if($train[$j][$num]==$attribute_name[$i]) 240 { 241 array_push($arraybranch,$train[$j]); 242 } 243 } 244 for($j=0;$j<count($arraybranch);$j++) 245 { 246 array_splice($arraybranch[$j],$num,1); 247 } 248 array_push($array_new,$arraybranch); 249 $num_branch_yes = 0; 250 $num_branch_no =0; 251 for($j=1;$j<count($arraybranch);$j++) 252 { 253 if($arraybranch[$j][count($arraybranch[$j])-1]==$flagsyes) $num_branch_yes++; 254 else $num_branch_no++; 255 } 256 if($num_branch_yes==count($arraybranch)-1)array_push($array_tree,array($attribute[0],$attribute_name[$i],$flagsyes)); 257 else if($num_branch_no==count($arraybranch)-1)array_push($array_tree,array($attribute[0],$attribute_name[$i],$flagsno)); 258 else { 259 $temp = Attributelist($arraybranch,$flagsyes,$flagsno); 260 array_push($array_tree,array($attribute[0],$attribute_name[$i],$temp[0])); 261 DecisionTree($arraybranch,$flagsyes,$flagsno,$array_tree,$count); 262 } 263 264 } 265 } 266 /* 267 echo "<pre>"; 268 print_r($array_tree); 269 echo "<pre>"; 270 //print_r("<br>".$count); 271 */ 272 return $array_tree; 273 274 } 275 //-------------------------------------------------------------------- 276 277 /* 278 279 *判断一个测试样本的类别 280 281 */ 282 //-------------------------------------------------------------------- 283 function ID3_Judge($test,$co,$decisiontree,$flagsyes,$flagsno) 284 { 285 //找寻根节点 286 $boot = $decisiontree[0][0]; 287 for($i=1;$i<count($test[0])-1;$i++) 288 { 289 if($boot==$test[0][$i]) 290 { 291 $num = $i; 292 break; 293 } 294 } 295 for($i=0;$i<count($decisiontree);$i++) 296 { 297 if(($decisiontree[$i][0]==$boot)&&($decisiontree[$i][1]==$test[$co][$num])) 298 { 299 if($decisiontree[$i][2]==$flagsyes) 300 { 301 $result = $flagsyes; 302 }else if($decisiontree[$i][2]==$flagsno){ 303 $result = $flagsno; 304 }else{ 305 $attributename = $decisiontree[$i][2]; 306 $mid = $i; 307 } 308 } 309 } 310 while($attributename!=NULL) 311 { 312 $boot = $attributename; 313 for($i=1;$i<count($test[0])-1;$i++) 314 { 315 if($boot==$test[0][$i]) 316 { 317 $num = $i; 318 break; 319 } 320 } 321 322 for($i=$mid;$i<count($decisiontree);$i++) 323 { 324 if(($decisiontree[$i][0]==$boot)&&($decisiontree[$i][1]==$test[$co][$num])) 325 { 326 if($decisiontree[$i][2]==$flagsyes) 327 { 328 $attributename = NULL; 329 $result = $flagsyes; 330 }else if($decisiontree[$i][2]==$flagsno){ 331 $attributename = NULL; 332 $result = $flagsno; 333 }else{ 334 $attributename = $decisiontree[$i][2]; 335 $mid = $i; 336 } 337 } 338 } 339 } 340 return $result; 341 } 342 //-------------------------------------------------------------------- 343 344 /* 345 *把.txt中的内容读到数组中保存 346 *$filename:文件名称 347 */ 348 349 //-------------------------------------------------------------------- 350 function gerFileContent($filename) 351 { 352 $array = array(NULL); 353 $content = file_get_contents($filename); 354 $result = explode("\r\n",$content); 355 356 for($j=0;$j<count($result);$j++) 357 { 358 $con = explode(" ",$result[$j]); 359 array_push($array,$con); 360 } 361 array_splice($array,0,1); 362 return $array; 363 } 364 //-------------------------------------------------------------------- 365 $train = gerFileContent("train.txt"); 366 $test = gerFileContent("test.txt"); 367 368 $array_tree = array(array(NULL,NULL,NULL)); 369 array_splice($array_tree,0,1); 370 $decisiontree = DecisionTree($train,Y,N,$array_tree); 371 372 for($i=1;$i<count($test);$i++) 373 { 374 $test[$i][count($test[0])-1] = ID3_Judge($test,$i,$decisiontree,Y,N); 375 } 376 377 /* 378 379 *将数组中的内容读到.txt中 380 381 */ 382 //-------------------------------------------------------------------- 383 $fp= fopen('result.txt','wb'); 384 for($i=0;$i<count($test);$i++) 385 { 386 $temp = NULL; 387 for($j=0;$j<count($test[$i]);$j++) 388 { 389 $temp = $test[$i][$j]."\t"; 390 fwrite($fp,$temp); 391 } 392 fwrite($fp,"\r\n"); 393 } 394 fclose($fp); 395 //-------------------------------------------------------------------- 396 397 /* 398 *打印输出决策树 399 */ 400 //-------------------------------------------------------------------- 401 echo "<pre>"; 402 print_r($decisiontree); 403 echo "<pre>"; 404 //-------------------------------------------------------------------- 405 406 /* 407 *打印输出 408 */ 409 //-------------------------------------------------------------------- 410 echo "<pre>"; 411 print_r($test); 412 echo "</pre>"; 413 //-------------------------------------------------------------------- 414 ?>