1. 程式人生 > 其它 >【轉】Maximal Information Coefficient (MIC)最大互資訊係數詳解與實現

【轉】Maximal Information Coefficient (MIC)最大互資訊係數詳解與實現

Maximal Information Coefficient (MIC)最大互資訊係數詳解與實現

————————————————
版權宣告:本文為CSDN博主「Font Tian」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/FontThrone/article/details/85227239

  • 感謝Font Tian的分享,僅作學術交流,如有侵權-聯絡後臺刪除~

覺得有用的話,歡迎一起討論相互學習~

MIC

MIC 即:Maximal Information Coefficient 最大互資訊係數。
使用MIC來衡量兩個基因之間的關聯程度,線性或非線性關係,相較於Mutual Information(MI)互資訊而言有更高的準確度。MIC是一種優秀的資料關聯性的計算方式。本篇文章將會詳細介紹MIC的演算法原理,優缺點以及Python的具體實現方式,並給出一個視覺化方案。

互資訊?

互資訊(Mutual Information)是資訊理論裡一種有用的資訊度量,它可以看成是一個隨機變數中包含的關於另一個隨機變數的資訊量,或者說是一個隨機變數由於已知另一個隨機變數而減少的不肯定性。這個已經是機器學習中老生常談的內容了,如果想不起來,請參考百度百科-互資訊

MIC的優越性

根據 MIC 的性質,MIC 具有普適性、公平性和對稱性。所謂普適性,是指在樣本量足夠大(包含了樣本的大部分資訊)時,能夠捕獲各種各樣的有趣的關聯,而不限定於特定的函式型別(如線性函式、指數函式或周期函式),或者說能均衡覆蓋所有的函式關係。一般變數之間的複雜關係不僅僅是通過單獨一個函式就能夠建模的,而是需要疊加函式來表現。所謂公平性,是指在樣本量足夠大時能為不同型別單噪聲程度相似的相關關係給出相近的係數。例如,對於一個充滿相同噪聲的線性關係和一個正弦關係,一個好的評價演算法應該給出相同或相近的相關係數。

演算法對比

理解公平性與普適性

對於普適性較好的函式,不同型別的關聯關係其起點應當是接近的。而且是接近於一的。

而對於公平性較好的比較方法,隨著噪音的增加,不同型別關聯關係函式變化應當是相近的。


由上可見,MIC擁有出色的普適性與公正性。

演算法原理

mic 基本原理會利用到互資訊概念,互資訊的概念使用以下方程來說明:

演算法原理的通俗解釋

演算法原理或許介紹的還是有點負責,下面還有一種簡單帶的解釋:

MIC計算分為三個步驟:

  1. 給定i、j,對XY構成的散點圖進行i列j行網格化,並求出最大的互資訊值
  2. 對最大的互資訊值進行歸一化
  3. 選擇不同尺度下互資訊的最大值作為MIC值

計算互資訊,求最大互資訊

互資訊的計算方案,下面就是劃分方式的一個示例。

那麼,給定了某個網格化方案後,如何計算其對應的互資訊值呢?這裡以上圖中紅色的網格化方案為例進行說明。紅色網格化方案將所有資料點分為四個區域:左上,右上,左下,右下。每個區域對應的資料點數量為1,4,4,1。將資料點數歸一化得到四個區域的資料點頻率,分別為0.1,0.4,0.4,0.1。也就是說,此時,X有兩種取值:左和右,Y有兩種取值:上和下。P(X=左,Y=上)=0.1,P(X=右,Y=上)=0.4,P(X=左,Y=下)=0.4,P(X=右,Y=下)=0.1。並且,P(X=左)=0.5,P(X=右)=0.5,P(Y=上)=0.5,P(Y=下)=0.5。根據互資訊計算公式,得到X和Y在這種分割槽下的互資訊為:

以此類推,算出哪種方案得到的互資訊值最大,最大的互資訊值是多少。

對最大的互資訊值進行歸一化

將得到的最大互資訊除以log(min(X,Y)),即為歸一化.這個與互資訊原公式有關。此處推導已經超出本文章範圍,不再做詳細解釋。只需要記住這一步是進行歸一化即可。

選擇不同尺度下互資訊的最大值作為MIC值

上面講述了給定i和j的情況下M(X,Y,D,i,j)的計算方法。這一步就是給定很多(i,j)值,計算每一種情況下M(X,Y,D,i,j)的值,將所有M(X,Y,D,i,j)中的最大那個值作為MIC值。注意的是,這裡的(i,j)是有條件的,要滿足,n表示資料集D的資料量。當然,B(n)這個值可以自己定,這裡是別人做實驗認為效果最好的值。

具體實現

在Python中的minepy類庫中實現了MIC演算法,具體使用如下。第一段程式碼展示的是直接使用MIC。而第二段函式則展示了,如何在sklearn的單變數選擇方法中使用該函式。除此之外值得一提的是,minepy含有很多其他係數,有興趣的話也可以研究一下。

引數解釋

  • 阿爾法(float資料型別,取值範圍為(0 ,1.0 ] 或 > = 4) 如果alpha的取值範圍在(0,1]之內,那麼B的取值範圍為(N ^α,4)其中n是樣本的數目。如果alpha的取值範圍是是> = 4。 alpha直接定義B引數。如果alpha高於樣本數(n),則它將被限制為n,因此B的取值實際上是個分段函式,具體公式為:B = min(alpha,n)。
  • c(float 取值範圍為大於)) - 確定比每個分割槽中的列多多個塊。預設值為15,這意味著當嘗試在x軸上繪製x網格線時,演算法將以最多15 * x個團塊開始。
import numpy as np
from minepy import MINE

x = np.linspace(0, 1, 1000)
y = np.sin(10 * np.pi * x) + x
mine = MINE(alpha=0.6, c=15)
mine.compute_score(x, y)

print("Without noise:")
print("MIC", mine.mic())
print()

np.random.seed(0)
y += np.random.uniform(-1, 1, x.shape[0])  # add some noise
mine.compute_score(x, y)

print("With noise:")
print("MIC", mine.mic())
Without noise:
MIC 1.0000000000000002

With noise:
MIC 0.5057166934173714
from minepy import MINE
from sklearn.datasets import load_iris
from sklearn.feature_selection import SelectKBest

irisdata = load_iris()


def mic(x, y):
    m = MINE()
    m.compute_score(x, y)
    return (m.mic(), 0.5)


#選擇 K 個最好的特徵,返回特徵選擇後的資料
irisdata_new =  SelectKBest(lambda X, Y: tuple(map(tuple,np.array(list(map(lambda x:mic(x, Y), X.T))).T)), k=3).fit_transform(irisdata.data, irisdata.target)

print(irisdata.data.shape,irisdata_new.shape)
(150, 4) (150, 3)

視覺化

在具體的使用中,有時候我們還需要進行視覺化來進行資料探索等等諸多工,因此我在此處還給出了視覺化的方案。首先我們還是使用UCI的紅酒質量資料集。然後利用minepy.MINE計算不同特徵之間的MIC,然後利用searbon進行矩陣視覺化。然後是一個更復雜的例子,同時這個例子也很好的證明了MIC的優秀效能。

下面是具體實現:

資料集可以前往我的Github下載

import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

# 從硬碟讀取資料進入記憶體
wine = pd.read_csv("/home/fonttian/Data/UCI/wine/wine.csv")

def MIC_matirx(dataframe, mine):

    data = np.array(dataframe)
    n = len(data[0, :])
    result = np.zeros([n, n])

    for i in range(n):
        for j in range(n):
            mine.compute_score(data[:, i], data[:, j])
            result[i, j] = mine.mic()
            result[j, i] = mine.mic()
    RT = pd.DataFrame(result)
    return RT


mine = MINE(alpha=0.6, c=15)
data_wine_mic = MIC_matirx(wine, mine)
data_wine_mic
0 1 2 3 4 5 6 7 8 9 10 11
0 0.999993 0.137049 0.359700 0.112888 0.104252 0.088545 0.087136 0.331103 0.363157 0.099565 0.091545 0.069389
1 0.137049 0.999859 0.342359 0.064291 0.088238 0.069755 0.075222 0.118709 0.091161 0.114195 0.097584 0.147521
2 0.359700 0.342359 0.999973 0.074586 0.094596 0.071099 0.114753 0.174092 0.228624 0.118638 0.094839 0.084114
3 0.112888 0.064291 0.074586 0.997599 0.098073 0.065086 0.073607 0.215840 0.081221 0.054224 0.076167 0.063269
4 0.104252 0.088238 0.094596 0.098073 0.999919 0.069770 0.093126 0.207912 0.106185 0.094228 0.137368 0.091436
5 0.088545 0.069755 0.071099 0.065086 0.069770 0.999986 0.478336 0.097462 0.061461 0.050779 0.046499 0.042377
6 0.087136 0.075222 0.114753 0.073607 0.093126 0.478336 0.999993 0.128559 0.105838 0.083387 0.123327 0.131426
7 0.331103 0.118709 0.174092 0.215840 0.207912 0.097462 0.128559 0.999997 0.171056 0.139684 0.257593 0.136607
8 0.363157 0.091161 0.228624 0.081221 0.106185 0.061461 0.105838 0.171056 0.999808 0.073231 0.074370 0.046885
9 0.099565 0.114195 0.118638 0.054224 0.094228 0.050779 0.083387 0.139684 0.073231 0.999890 0.118204 0.150187
10 0.091545 0.097584 0.094839 0.076167 0.137368 0.046499 0.123327 0.257593 0.074370 0.118204 0.999986 0.210051
11 0.069389 0.147521 0.084114 0.063269 0.091436 0.042377 0.131426 0.136607 0.046885 0.150187 0.210051 0.996521
# MIC結果矩陣視覺化
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline

def ShowHeatMap(DataFrame):
    colormap = plt.cm.RdBu
    ylabels = DataFrame.columns.values.tolist()
    f, ax = plt.subplots(figsize=(14, 14))
    ax.set_title('GRA HeatMap')
    sns.heatmap(DataFrame.astype(float),
                cmap=colormap,
                ax=ax,
                annot=True,
                yticklabels=ylabels,
                xticklabels=ylabels)
    plt.show()


ShowHeatMap(data_wine_mic)

一個更復雜的例子

下面我們生成一組資料來進行MIC的測試,生成資料的公式來自資料集採用Friedman #1迴歸資料(這篇論文中的資料)。資料是用這個公式產生的:

X1到X5是由單變數分佈生成的,e是標準正態變數N(0,1)。另外,原始的資料集中含有5個噪音變數 X5,…,X10,跟響應變數是獨立的。我們增加了4個額外的變數X11,…X14,分別是X1,…,X4的關聯變數,通過f(x)=x+N(0,0.01)生成,這將產生大於0.999的關聯絡數。關於特徵選擇的Bryan__ 也有一篇不錯的文章-結合Scikit-learn介紹幾種常用的特徵選擇方法,下面的資料生成程式碼就是從這篇文章中的程式碼修改而來的。

# 固定隨機數,以確保每次生成的隨機數固定
np.random.seed(42)

size = 750
X = np.random.uniform(0, 1, (size, 14))

#"Friedamn #1” regression problem
Y = (10 * np.sin(np.pi * X[:, 0] * X[:, 1]) + 20 * (X[:, 2] - .5)**2 +
     10 * X[:, 3] + 5 * X[:, 4] + np.random.normal(0, 1))
#Add 3 additional correlated variables (correlated with X1-X3)
X[:, 10:] = X[:, :4] + np.random.normal(0, .025, (size, 4))

names = ["x%s" % i for i in range(1, 15)]

# 構建生成DF資料集
Friedman_regression_data = pd.DataFrame(X)
Friedman_regression_data['y'] = Y

# 獲取MIC矩陣
mine = MINE(alpha=0.6, c=15)
data_wine_mic = MIC_matirx(Friedman_regression_data, mine)
# 進行結果視覺化
ShowHeatMap(data_wine_mic)

程式碼與結果解讀
首先固定隨機數,以確保每次生成的隨機數固定。然後生成一個750行,10列取值範圍在0-1內的隨機矩陣。之後按照"Friedamn #1"生成Y,並將X的前四列,增加隨機項,生成11-14項特徵。

之後就是將numpy陣列修改為dataframe陣列,並傳入MIC矩陣的計算函式,最終進行seaborn進行矩陣視覺化。

結果非常不錯除了中間特徵與自己本身的高度相關之外。我們可以很明顯的發現第1-4特徵與第11-14項特徵MIC為1.這已經充分證明了MIC優秀的效能。

參考與學習推薦

首先非常感謝已經有兩位網上的同行以及寫過有關MIC的很優秀的文章,同時也感謝wiki百科以及其他網路資料。