機器學習-ID3決策樹算法(附matlab/octave代碼)


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;

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM