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("
",$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]." ";
390 fwrite($fp,$temp);
391 }
392 fwrite($fp,"
");
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 ?>