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;
