文章目錄
相關文章:
1. 信息熵 Information Entropy
信息是個很抽象的概念。人們常常說信息很多,或者信息較少,但卻很難說清楚信息到底有多少。比如一本五十萬字的中文書到底有多少信息量。直到1948年,香農提出了“信息熵”的概念,才解決了對信息的量化度量問題。
信息熵
這個詞是香農從熱力學中借用過來的。熱力學中的熱熵是表示分子狀態混亂程度的物理量。香農用信息熵的概念來描述不確定性
。
- 隨機變量的信息熵計算公式:
- 信息熵越大,則表示不確定性越高。
- 在文本中,當不同的詞彙越多時,其信息熵越大,直觀上來說就是所包含的信息越多
熵:在物理的熱力學中,用熵來表示分子狀態混亂程度。當一個物體溫度越高時,其內部粒子活動越劇烈,也越混亂。因此混亂程度越高,熵越大。
1.1 信息熵公式推導
- 計算取出結果與原順序相同的概率:
- 將概率公式取以2爲底的對數變換,得到信息量的公式:
- 隨機變量的信息熵計算公式::
對於樣本集合來說,隨機變量是樣本的類別,即假設樣本有個類別,樣本總數爲,則類別的概率是。
因此樣本集合的經驗熵爲:
例1:假設有四個球,從中隨機放回地抽出四個球,下面計算各個事件的信息熵:
1.紅紅紅紅
,則事件的信息熵:
2.紅紅紅藍
,則事件的信息熵:
3.紅紅藍藍
,則事件的信息熵:
由上面三個例子可以看出,當混亂程度越高時,信息熵越大。
關於各類熵的定義及推導,可參考這篇文章。
2. 信息增益 Information Gain
信息增益:
對於待劃分的數據集,其信息熵大小是固定的,但是劃分後子代熵之和是不定的。子代熵越小說明使用此特徵劃分得到的子集不確定性越小(純度越高),因此父代與子代的信息熵之差
(信息增益
)越大,說明使用當前特徵劃分數據集時,其純度上升的更快[1]。
與決策樹關係:
我們在構建最優的決策樹時總希望能夠快速到達村度更高的集合,這一點可以參考優化算法中的梯度下降(每一步沿着負梯度方法最小化損失函數使函數值快速減小)同理,在決策樹構建的過程中我們總是希望集合往最快到達純度更高的子集合方向發展,因此我們總是選擇使得信息增益最大的特徵來劃分當前數據集。
使用特徵劃分數據集,計算劃分前後各個數據集的信息熵,並計算信息增益
:
其中,假設特徵將數據集劃分爲個子代,則爲劃分後子代的平均信息熵:
例2:假設我們在調查性別與活躍度哪一個對用戶流失影響越大。[2]
樣本如下:
Gender | Activation | is_lost |
---|---|---|
M | H | 0 |
F | M | 0 |
M | L | 1 |
F | H | 0 |
M | H | 0 |
M | M | 0 |
M | M | 1 |
F | M | 0 |
F | L | 1 |
F | M | 0 |
F | H | 0 |
M | L | 1 |
F | L | 0 |
M | H | 0 |
M | H | 0 |
按性別分類:
\ | Lost | No-lost | Sum |
---|---|---|---|
Whole | 5 | 10 | 15 |
Male | 3 | 5 | 8 |
Female | 2 | 5 | 7 |
整體熵:
性別熵:
性別信息增益
:
按活躍度分類
\ | Lost | No-lost | Sum |
---|---|---|---|
Whole | 5 | 10 | 15 |
Hight | 0 | 6 | 6 |
Mid | 1 | 4 | 5 |
Low | 4 | 0 | 4 |
活躍度熵:
活躍度信息增益
:
活躍度信息增益比性別信息增益大,也就是說,活躍度對用戶流失的影響比性別大。
2.1 信息增益最大化
2.1.1 利用離散特徵進行分類
- 計算父代熵
- 計算子代熵
- 計算信息增益,按信息增益較大的進行分類
- 如果分類後結果不理想,可將其分類作爲父代繼續進行分類
例3:仍以上面的例子爲例,之前,我們已經計算出了活躍度對於用戶流失的影響較大,當用戶的活躍度爲Hight時,用戶流失爲0,當用戶活躍度爲Low時,用戶全部流失,因此可以得到:
可以看到,Hight和Low組的信息熵爲0,純度已達到最高;但是Mid組純度未達到最高,因此以Mid組的數據作爲父代,重複例2的過程,由於例2數據只有兩個特徵,因此只能嘗試使用性別分類;若例2數據有2個以上特徵,則此時可以重複例2過程,計算其餘特徵的信息增益,並選取信息增益最大的特徵作爲分類依據。由此也可以看出,離散特徵決策樹的最大深度不超過其特徵數
(連續特徵決策樹的特徵可多次使用)。
下面嘗試使用性別分組,Mid組的樣本:
Gender | Activation | is_lost |
---|---|---|
F | M | 0 |
M | M | 0 |
M | M | 1 |
F | M | 0 |
F | M | 0 |
對Mid組使用性別分類後的結果:
2.1.2 利用連續特徵進行分類
2.1.2.1 二分法
因爲連續特徵屬性的可取值數目不再有限,因此不能像前面處理離散屬性一樣枚舉離散屬性來對節點進行劃分,因此需要對連續屬性離散化。
常用的離散化策略是二分法:
給定訓練集和連續屬性,假定在上出現了個不同的取值,先把這些值從小到達排序,記爲,基於劃分點可以將分爲子集和,其中是包含那些屬性上取值不大於的樣本,則包含哪些在屬性上取值大於的樣本。顯然,對相鄰的屬性取值與來說,在區間中取任意值所產生的劃分結果相同。因此,對連續屬性,我們可考慮包含個元素的候選劃分點集合:
即把區間的中位點作爲候選劃分點,然後就可以像前面處理離散屬性值那樣來考慮這些劃分點,並選擇最後的劃分點進行樣本集合的劃分,使用的公式如下:
其中是樣本集基於劃分點二分後的信息增益。
劃分的時候,選擇使最大的劃分點。[3]
2.1.2.2 信息熵、信息增益及二分法的Python實現
例4:下面以周志華《機器學習》—西瓜數據集3.0 爲例,計算特徵“密度”的最佳劃分點以及其信息增益,數據如下:
import pandas as pd
import numpy as np
df = pd.read_csv("Data/Watermelon_Data.txt")
df['好瓜'] = df['好瓜'].map({'是':1, '否':0})
df
編號 | 色澤 | 根蒂 | 敲聲 | 紋理 | 臍部 | 觸感 | 密度 | 含糖率 | 好瓜 | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 青綠 | 蜷縮 | 濁響 | 清晰 | 凹陷 | 硬滑 | 0.697 | 0.460 | 1 |
1 | 2 | 烏黑 | 蜷縮 | 沉悶 | 清晰 | 凹陷 | 硬滑 | 0.774 | 0.376 | 1 |
2 | 3 | 烏黑 | 蜷縮 | 濁響 | 清晰 | 凹陷 | 硬滑 | 0.634 | 0.264 | 1 |
3 | 4 | 青綠 | 蜷縮 | 沉悶 | 清晰 | 凹陷 | 硬滑 | 0.608 | 0.318 | 1 |
4 | 5 | 淺白 | 蜷縮 | 濁響 | 清晰 | 凹陷 | 硬滑 | 0.556 | 0.215 | 1 |
5 | 6 | 青綠 | 稍蜷 | 濁響 | 清晰 | 稍凹 | 軟粘 | 0.403 | 0.237 | 1 |
6 | 7 | 烏黑 | 稍蜷 | 濁響 | 稍糊 | 稍凹 | 軟粘 | 0.481 | 0.149 | 1 |
7 | 8 | 烏黑 | 稍蜷 | 濁響 | 清晰 | 稍凹 | 硬滑 | 0.437 | 0.211 | 1 |
8 | 9 | 烏黑 | 稍蜷 | 沉悶 | 稍糊 | 稍凹 | 硬滑 | 0.666 | 0.091 | 0 |
9 | 10 | 青綠 | 硬挺 | 清脆 | 清晰 | 平坦 | 軟粘 | 0.243 | 0.267 | 0 |
10 | 11 | 淺白 | 硬挺 | 清脆 | 模糊 | 平坦 | 硬滑 | 0.245 | 0.057 | 0 |
11 | 12 | 淺白 | 蜷縮 | 濁響 | 模糊 | 平坦 | 軟粘 | 0.343 | 0.099 | 0 |
12 | 13 | 青綠 | 稍蜷 | 濁響 | 稍糊 | 凹陷 | 硬滑 | 0.639 | 0.161 | 0 |
13 | 14 | 淺白 | 稍蜷 | 沉悶 | 稍糊 | 凹陷 | 硬滑 | 0.657 | 0.198 | 0 |
14 | 15 | 烏黑 | 稍蜷 | 濁響 | 清晰 | 稍凹 | 軟粘 | 0.360 | 0.370 | 0 |
15 | 16 | 淺白 | 蜷縮 | 濁響 | 模糊 | 平坦 | 硬滑 | 0.593 | 0.042 | 0 |
16 | 17 | 青綠 | 蜷縮 | 沉悶 | 稍糊 | 稍凹 | 硬滑 | 0.719 | 0.103 | 0 |
- 以數據集中的
“密度”
爲例,決策樹開始學習時,根節點包含的17個訓練樣本在屬性上取值均不同。我們把“密度”這些值從小到大排序:
Density_arr = df['密度'].sort_values()
f = lambda x: round(x,3) # 保留三位小數
Density_arr = Density_arr.apply(f)
print(Density_arr.tolist())
[0.243, 0.245, 0.343, 0.36, 0.403, 0.437, 0.481, 0.556, 0.593, 0.608, 0.634, 0.639, 0.657, 0.666, 0.697, 0.719, 0.774]
- 根據公式(7)計算分割點:
T_midu = (Density_arr+Density_arr.shift(-1))/2
T_midu = T_midu[:-1].apply(f) # 二分法獲得的(n-1)個分割點
T_midu.index=np.arange(len(T_midu))
print(T_midu.tolist())
[0.244, 0.294, 0.352, 0.382, 0.42, 0.459, 0.518, 0.575, 0.601, 0.621, 0.637, 0.648, 0.661, 0.681, 0.708, 0.746]
- 計算父代信息熵(Ent_D)
# 以西瓜質量劃分集合
def divide_arr(arr):
arr = df['好瓜'].iloc[arr.index.values.tolist()]
arr_len = len(arr)
Left_len = sum(arr == 1)
Right_len = arr_len - Left_len
return arr_len, Left_len, Right_len
# 計算集合信息熵
def entropy(arr):
arr_len, Left_len, Right_len = divide_arr(arr)
L_frac = Left_len/arr_len
R_frac = Right_len/arr_len
if L_frac==0:
Ent = -(R_frac*np.log2(R_frac))
elif R_frac==0:
Ent = -(L_frac*np.log2(L_frac))
else:
Ent = -(L_frac*np.log2(L_frac) + R_frac*np.log2(R_frac))
Ent = round(Ent,3)
return Ent
Ent_D = entropy(Density_arr)
Ent_D
0.998
- 利用第2步獲得的分割點,計算(n-1)種分法對應的子代信息熵(gen_entropy_arr):
# 利用分割點二分父代
def binary(arr, node):
arr_L = arr[arr<=node]
arr_L.name = 'arr_L'
arr_R = arr[arr>node]
arr_R.name = 'arr_R'
return arr_L, arr_R
# 計算子代熵
def gen_entropy(arr, node):
arr_L, arr_R = binary(arr, node)
len_L = len(arr_L)
len_R = len(arr_R)
len_D = len_L + len_R
Ent_gen = len_L/len_D*entropy(arr_L) + len_R/len_D*entropy(arr_R)
Ent_gen = round(Ent_gen,3)
return Ent_gen
gen_entropy_arr = pd.Series(np.empty(len(T_midu)))
for i, cut in enumerate(T_midu):
gen_entropy_arr.iloc[i] = gen_entropy(Density_arr, cut)
- 計算各類分法的信息增益:
df2 = pd.concat([T_midu, gen_entropy_arr], axis=1)
df2.columns=['劃分點','子集熵']
df2['信息增益'] = Ent_D - df2['子集熵']
df2
劃分點 | 子集熵 | 信息增益 | |
---|---|---|---|
0 | 0.244 | 0.941 | 0.057 |
1 | 0.294 | 0.880 | 0.118 |
2 | 0.352 | 0.811 | 0.187 |
3 | 0.382 | 0.735 | 0.263 |
4 | 0.420 | 0.904 | 0.094 |
5 | 0.459 | 0.967 | 0.031 |
6 | 0.518 | 0.994 | 0.004 |
7 | 0.575 | 0.995 | 0.003 |
8 | 0.601 | 0.995 | 0.003 |
9 | 0.621 | 0.994 | 0.004 |
10 | 0.637 | 0.967 | 0.031 |
11 | 0.648 | 0.991 | 0.007 |
12 | 0.661 | 0.997 | 0.001 |
13 | 0.681 | 0.973 | 0.025 |
14 | 0.708 | 0.997 | 0.001 |
15 | 0.746 | 0.931 | 0.067 |
- 因此信息增益最大值爲0.263,對應劃分點爲0.382,如下所示:
print(df2.iloc[df2['信息增益'].idxmax()])
劃分點 0.382
子集熵 0.735
信息增益 0.263
Name: 3, dtype: float64
繼續對其他的特徵進行以上步驟,可以得到其他特徵的信息增益,因此該連續特徵的決策樹的第一個分割點爲信息增益最大的特徵所對應的分割點。
下面是本數據集中各特徵的信息增益值:[4]
由此可見,“紋理”的信息增益量值最大,因此”紋理“被選作根節點劃分屬性。只要重複以上過程,就能構造出一顆決策樹:
需要注意的是:與離散屬性不同,若當前節點劃分屬性爲連續屬性,該屬性還可以作爲其後代節點的劃分屬性。如下圖的一顆決策樹,“含糖率”這個屬性在根節點用了一次,後代節點也用了一次,只是兩次劃分點取值不同。
參考資料
[1] Tomcater321.決策樹–信息增益,信息增益比,Geni指數的理解
[EB/OL].https://blog.csdn.net/Tomcater321/article/details/80699044, 2018-06-14.
[2] It_BeeCoder.機器學習中信息增益的計算方法 [EB/OL].https://blog.csdn.net/it_beecoder/article/details/79554388, 2018-03-14.
[3] 天澤28.決策樹(decision tree)(三)——連續值處理 [EB/OL].https://blog.csdn.net/u012328159/article/details/79396893, 2018-02-28.
[4] 天澤28.決策樹(decision tree)(一)——構造決策樹方法 [EB/OL].https://blog.csdn.net/u012328159/article/details/70184415, 2017-04-18.