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計算分為三個步驟:
- 給定i、j,對XY構成的散點圖進行i列j行網格化,並求出最大的互信息值
- 對最大的互信息值進行歸一化
- 選擇不同尺度下互信息的最大值作為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百科以及其他網絡資料。




