ID3決策樹算法是基於信息增益來構建的,信息增益可以由訓練集的信息熵算得,這里舉一個簡單的例子
data=[心情好 天氣好 出門
心情好 天氣不好 出門
心情不好 天氣好 出門
心情不好 天氣不好 不出門]
前面兩列是分類屬性,最后一列是分類
分類的信息熵可以計算得到:
出門=3,不出門=1,總行數=4
分類信息熵 = -(3/4)*log2(3/4)-(1/4)*log2(1/4)
第一列屬性有兩類,心情好,心情不好
心情好 ,出門=2,不出門=0,行數=2
心情好信息熵=-(2/2)*log2(2/2)+(0/2)*log2(0/2)
同理
心情不好信息熵=-(1/2)*log2(1/2)-(1/2)*log2(1/2)
心情的信息增益=分類信息熵 - 心情好的概率*心情好的信息熵 - 心情不好的概率*心情不好的信息熵
由此可以得到每個屬性對應的信息熵,信息熵最大的即為最優划分屬性。
還是這個例子,加入最優划分屬性為心情
然后分別在心情屬性的每個具體情況下的分類是否全部為同一種,若為同一種則該節點標記為此類別,
這里我們在心情好的情況下不管什么天氣結果都是出門所以,有了
心情不好的情況下有不同的分類結果,繼續計算在心情不好的情況下,其它屬性的信息增益,
把信息增益最大的屬性作為這個分支節點,這個我們只有天氣這個屬性,那么這個節點就是天氣了,
天氣屬性有兩種情況,如下圖
在心情不好並且天氣好的情況下,若分類全為同一種,則改節點標記為此類別
有訓練集可以,心情不好並且天氣好為出門,心情不好並且天氣不好為不出門,結果入下圖
對於分支節點下的屬性很有可能沒有數據,比如,我們假設訓練集變成
data=[心情好 晴天 出門
心情好 陰天 出門
心情好 雨天 出門
心情好 霧天 出門
心情不好 晴天 出門
心情不好 雨天 不出門
心情不好 陰天 不出門]
如下圖:
在心情不好的情況下,天氣中並沒有霧天,我們如何判斷霧天到底是否出門呢?我們可以采用該樣本最多的分類作為該分類,
這里天氣不好的情況下,我們出門=1,不出門=2,那么這里將不出門,作為霧天的分類結果
在此我們所有屬性都划分了,結束遞歸,我們得到了一顆非常簡單的決策樹。
下面附上我的實現ID3決策樹算法代碼:(octave/matlab,該程序本人已經驗證過可以執行且結果正確,這里屬性集我偷了一個懶,
沒有標識出具體屬性名,我是使用矩陣中的列號)
著名的還有C4.5決策樹算法,它是ID3的改進,作者都是同一個人,羅斯昆蘭
%生成決策樹ID3算法 %data:訓練集 %feature:屬性集 function [node] =createTree(data,feature) type=mostType(data); [m,n]=size(data); %生成節點node %value:分類結果,若為null則表示該節點是分支節點 %name:節點划分屬性 %type:節點屬性值 %children:子節點 node=struct('value','null','name','null','type','null','children',[]); temp_type=data(1,n); temp_b=true; for i=1:m if temp_type!=data(i,n) temp_b=false; end end %樣本中全為同一分類結果,則node節點為葉子節點 if temp_b==true node.value=data(1,n); return; end %屬性集合為空,將結果標記為樣本中最多的分類 if sum(feature)==0 node.value=type; return; end feature_bestColumn=bestFeature(data); best_feature=getData()(:,feature_bestColumn); best_distinct=unique(best_feature); best_num=length(best_distinct); best_proc=zeros(best_num,2); best_proc(:,1)=best_distinct(:,1); %循環該屬性的每一個值 for i=1:best_num Dv=[]; Dv_index=1; %為node創建一個bach_node分支,設樣本data中改屬性值為best_proc(i,1)的集合為Dv bach_node=struct('value','null','name','null','type','null','children',[]); for j=1:m if best_proc(i,1)==data(j,feature_bestColumn) Dv(Dv_index,:)=data(j,:); Dv_index=Dv_index+1; end end %Dv為空則將結果標記為樣本中最多的分類 if length(Dv)==0 bach_node.value=type; bach_node.type=best_proc(i,1); bach_node.name=feature_bestColumn; node.children(i)=bach_node; return; else feature(feature_bestColumn)=0; %遞歸調用createTree方法 bach_node=createTree(Dv,feature); bach_node.type=best_proc(i,1); bach_node.name=feature_bestColumn; node.children(i)=bach_node; end end end %獲取最優划分屬性 function [column] = bestFeature(data) [m,n]=size(data); featureSize=n-1; gain_proc=zeros(featureSize,2); entropy=getEntropy(data); for i=1:featureSize gain_proc(i,1)=i; gain_proc(i,2)=getGain(entropy,data,i); end for i=1:featureSize if gain_proc(i,2)==max(gain_proc(:,2)) column=i; break; end end end %計算樣本最多的結果 function [res] = mostType(data) [m,n]=size(data); res_distinct = unique(data(:,n)); res_proc = zeros(length(res_distinct),2); res_proc(:,1)=res_distinct(:,1); for i=1:length(res_distinct) for j=1:m if res_proc(i,1)==data(j,n) res_proc(i,2)=res_proc(i,2)+1; end end end for i=1:length(res_distinct) if res_proc(i,2)==max(res_proc(:,2)) res=res_proc(i,1); break; end end end %計算信息熵 function [entropy] = getEntropy(data) entropy=0; [m,n]=size(data); label=data(:,n); label_distinct=unique(label); label_num=length(label_distinct); proc=zeros(label_num,2); proc(:,1)=label_distinct(:,1); for i=1:label_num for j=1:m if proc(i,1)==data(j,n) proc(i,2)=proc(i,2)+1; end end proc(i,2)=proc(i,2)/m; end for i=1:label_num entropy=entropy-proc(i,2)*log2(proc(i,2)); end end %計算信息增益 function [gain] = getGain(entropy,data,column) [m,n]=size(data); feature=data(:,column); feature_distinct=unique(feature); feature_num=length(feature_distinct); feature_proc=zeros(feature_num,2); feature_proc(:,1)=feature_distinct(:,1); f_entropy=0; for i=1:feature_num feature_data=[]; feature_proc(:,2)=0; feature_row=1; for j=1:m if feature_proc(i,1)==data(j,column) feature_proc(i,2)=feature_proc(i,2)+1; end if feature_distinct(i,1)==data(j,column) feature_data(feature_row,:)=data(j,:); feature_row=feature_row+1; end end f_entropy=f_entropy+feature_proc(i,2)/m*getEntropy(feature_data); end gain=entropy-f_entropy;