機器學習中:信息熵,信息增益,信息增益比,原理,案例,代碼實現。

目錄

引言

原理

信息熵

條件熵

信息增益

信息增益算法流程

信息增益比

案例

信息熵求解

信息增益求解

信息增益比求解

結果分析

案例的代碼實現


引言

在機器學習和深度學習中,經常會用到信息熵(entropy)這個概念,可以理解爲熵表示的是隨機變量不確定度的衡量。例如概率0.5比概率0.3的不確定度要高。

原理

信息熵

設X是一個取值有限的離散隨機變量,其概率分佈爲:P(X=x_i)=p_i, i=1,2,3,...,n,則隨機變量X的熵定義爲H(X)=-\sum_{i=1}^{n}p_ilogp_i

通常log取2或者3,得到的熵的單位分別稱作比特或納特。從這就可以知道,熵依賴X的分佈,和X的取值無關,所以也可以把X的熵記做H(p):

H(p)=-\sum_{i=1}^{n}p_ilogp_i

當隨機變量只有兩個取值的時候,例如0,1,那麼X的分佈爲:

P(X=1)=p,P(X=0)=1-p,0\leq p\leq 1

那麼X的熵爲:

H(p)=-p\log_2p-(1-p)log_2(1-p)

H(p)的變化曲線如下:

從上圖中可以看出,當p=0或者1的時候,熵爲0,這個時候不確定度最低,因爲p=0或1已經決定x屬於什麼了。

同理,當p=0.5的時候不確定度最高,此時很難分清x到底是什麼。

 

條件熵

設隨機變量(X,Y)的聯合概率分佈爲:P(X=x_i,Y=y_i)=p_i_j

條件熵H(Y|X)表示在已知隨機變量X的條件下,Y的不確定度,因此H(Y|X)=\sum_{i=1}^{n}p_iH(Y|X=x_i)

這裏p_i=P(X=x_i)

當熵和條件熵是有訓練數據估計而來的,那麼對應的熵和條件熵稱爲經驗熵和經驗條件熵。

 

信息增益

信息增益是表示數據集中某個特徵X的信息使類Y的信息的不確定性減少的程度,即特徵X讓類Y不確定度降低。

特徵A對訓練數據集D的信息的信息增益g(D,A),定義爲集合D的熵H(D)與特徵A給定條件下D的條件熵H(D|A)之差

g(D,A)=H(D)-H(D|A)

其中H(D)H(D|A)之差成爲互信息

 

信息增益算法流程

數據集爲D;樣本容量爲|D|,即樣本個數。

K爲分類個數,|C_k|表示屬於類別C_k的樣本個數,\sum_{k=1}^{K}|C_k|=|D|

特徵A取值有a_1,a_2,...,a_n,根據A的取值,把D劃分成n個子集D_1,D_2,...,D_n|D_i|D_i的樣本個數,\sum_{i=1}^{n}|D_i|=|D|

 

子集D_i中屬於C_k的樣本的集合爲D_i_k|D_i_k|D_i_k的樣本個數。

輸入:訓練數據集D和特徵A

輸出:特徵A對數據集D的信息增益g(D,A)

  • 計算數據D的經驗熵H(D)=-\sum_{k=1}^{K}\frac{C_k}{D}log_2\frac{C_k}{D}
  • 計算特徵A對數據集D的經驗條件熵H(D|A)=-\sum_{i=1}^{n}\frac{|D_i|}{|D|}\sum_{k=1}^{K}\frac{|D_i_k|}{|D_i|}log_2\frac{|D_i_k|}{|D_i|}
  • 計算信息增益g(D,A)=H(D)-H(D|A)

 

信息增益比

有時候以信息增益來劃分訓練數據集的特徵,會存在偏向於選擇取值較多的特徵問題,使用信息增益比可以對這一個問題進行校正,成文一種更加權衡的選擇標準。

特徵A對訓練數據D的信息增益比g_R(D,A)定義爲信息增益g(D,A)與訓練數據D關於特徵A的值的熵之比:

g_R(D,A)=\frac{g(D,A)}{H_A(D)},其中H_A(D)=-\sum_{i=1}^{n}\frac{|D_i|}{|D|}log_2\frac{|D_i|}{|D|},n是特徵A取值的個數。

 

案例

表中是貸款申請表,最後的類別代表是否給予貸款的分類,求訓練集信息熵、信息增益和信息增益比。

 

信息熵求解

從類別中可以知道,是有9個,否有6個,所以信息熵爲0.971:

 

信息增益求解

這裏需要對每個特徵分別單獨求解,例如信貸特徵,有三類。一般、好和非常好分別是:5,6,4。

在一般中,是有1個,否有4個;

在好中,是有4個,否有2個;

在非常好中,是有4個,否有0個。所以計算如下:

 

信息增益比求解

上面已經計算過信息增益了,因此只需計算特徵熵即可,計算如下:

 

結果分析

如果以信息增益爲特徵選擇標準,可以知道房子的權重最大,因此優先選擇房子作爲首要特徵,信貸特徵其次。

信息增益比則是對信息增益進行了校正,從結果中可以知道,房子特徵依舊是首要特徵,但是工資特徵其次,而不是信息增益中的信貸。

 

案例的代碼實現

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

from collections import Counter
import math
from math import log

import pprint


def create_data():
    datasets = [['青年', '否', '否', '一般', '否'],
                ['青年', '否', '否', '好', '否'],
                ['青年', '是', '否', '好', '是'],
                ['青年', '是', '是', '一般', '是'],
                ['青年', '否', '否', '一般', '否'],
                ['中年', '否', '否', '一般', '否'],
                ['中年', '否', '否', '好', '否'],
                ['中年', '是', '是', '好', '是'],
                ['中年', '否', '是', '非常好', '是'],
                ['中年', '否', '是', '非常好', '是'],
                ['老年', '否', '是', '非常好', '是'],
                ['老年', '否', '是', '好', '是'],
                ['老年', '是', '否', '好', '是'],
                ['老年', '是', '否', '非常好', '是'],
                ['老年', '否', '否', '一般', '否'],
                ]
    labels = [u'年齡', u'有工作', u'有自己的房子', u'信貸情況', u'類別']
    # 返回數據集和每個維度的名稱
    return datasets, labels


# 熵
def calc_ent(datasets):
    data_length = len(datasets)
    label_count = {}
    for i in range(data_length):
        label = datasets[i][-1]
        if label not in label_count:
            label_count[label] = 0
        label_count[label] += 1
    ent = -sum([(p / data_length) * log(p / data_length, 2) for p in label_count.values()])
    return ent


# 經驗條件熵
def cond_ent(datasets, axis=0):
    data_length = len(datasets)
    feature_sets = {}
    for i in range(data_length):
        feature = datasets[i][axis]
        if feature not in feature_sets:
            feature_sets[feature] = []
        feature_sets[feature].append(datasets[i])
    cond_ent = sum([(len(p) / data_length) * calc_ent(p) for p in feature_sets.values()])
    return cond_ent


# 信息增益
def info_gain(ent, cond_ent):
    return ent - cond_ent


def info_gain_train(datasets):
    count = len(datasets[0]) - 1
    ent = calc_ent(datasets)
    best_feature = []
    for c in range(count):
        c_info_gain = info_gain(ent, cond_ent(datasets, axis=c))
        best_feature.append((c, c_info_gain))
        print('特徵({}) - info_gain - {:.3f}'.format(labels[c], c_info_gain))
    # 比較大小
    best_ = max(best_feature, key=lambda x: x[-1])
    return '特徵({})的信息增益最大,選擇爲根節點特徵'.format(labels[best_[0]])


datasets, labels = create_data()
train_data = pd.DataFrame(datasets, columns=labels)
print(train_data)
print('特徵信息增益爲:', info_gain_train(np.array(datasets)))

結果如下:(值計算了信息增益)

程序運算結果與手動計算結果一致。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章