Partial Dependence就是用來解釋某個特征和目標值y的關系的,一般是通過畫出Partial Dependence Plot(PDP)來體現。
PDP是依賴於模型本身的,所以我們需要先訓練模型(比如訓練一個random forest模型)。假設我們想研究y和特征\(X_1\)的關系,那么PDP就是一個關於\(X_1\)和模型預測值的函數。我們先擬合了一個隨機森林模型RF(X),然后用\(X_k^{i}\)表示訓練集中第k個樣本的第i個特征,那么PDP的函數就是
也就是說PDP在\(X_1\)的值,就是把訓練集中第一個變量換成\(X_1\)之后,原模型預測出來的平均值。
根據\(X_1\)的不同取值,\(f(X_1)\)就可以練成折線,這個折線就是Partial Dependence Plot,橫軸是\(X_1\),縱軸就是Partial Dependence。
下圖就是一個例子
自己寫代碼模擬:
from sklearn.tree import DecisionTreeRegressor
from sklearn.inspection import partial_dependence
from sklearn.datasets import load_boston
import numpy as np
import matplotlib.pyplot as plt
data = load_boston()
X, y = data.data, data.target
dtr = DecisionTreeRegressor()
dtr.fit(X,y)
def my_pdp(model, X, feat_idx):
fmax, fmin = np.max(X[:, feat_idx]), np.min(X[:, feat_idx])
frange = np.linspace(fmin, fmax, 100)
preds = []
for x in frange:
X_ = X.copy()
X_[:, feat_idx] = x
pred = model.predict(X_)
preds.append(np.mean(pred))
return (frange, np.array(preds))
del dtr.classes_
my_data = my_pdp(dtr, X, 0)
sk_data = partial_dependence(dtr, X = X, features = [0], percentiles=[0,1])
plt.subplot(121)
plt.plot(my_data[0], my_data[1])
plt.subplot(122)
plt.plot(sk_data[1][0], sk_data[0][0])
plt.show()
Github python library PDPbox
優點
pdp的計算是直觀的:partial dependence function 在某個特定特征值位置表示預測的平均值,如果我們強制所有的數據點都取那個特征值。在我的經驗中,lay people(普通人,沒有專業知識的大眾)通常都可以很快理解PDPs的idea。
如果你要計算的PDP的特征和其它特征沒有關聯,那么PDP可以完美的展示出這個特征大體上上如何影響預測值的。在不相關的情況下,解釋是清晰的:PDP展示了平均預測值在某個特征改變時是如何變化的。如果特征是相互關聯的,這會變得更加復雜。
不足
實際分析PDP時的最大特征個數是2。這不是PDP的錯誤,而是由於我們人無法想象超過三維的空間。
有一些 PDP並不展示特征分布。忽略分布可能會造成誤解,因為你可能會過度解讀具有少量數據的地方。這個問題通過展示一個rug或者histogram在x軸上的方式很容易解決。
獨立性假設是PDP的最大問題,它假設計算的特征和其它特征是不相關的。當特征是相關的時候,我們創造的新的數據點在特征分布的空間中出現的概率是很低的。對這個問題的一個解決方法就是Accumulate Local Effect plots,或者簡稱ALE plots,它工作在條件分布下而不是邊緣分布下。
多種類的影響可能會被隱藏,因為PDP僅僅展示邊際影響的平均值。假設對於一個要計算的特征,一半的數據點對預測有正相關性,一半的數據點對預測有負相關性。PD曲線可能會是一個水平的直線,因為兩半數據點的影響可能會互相抵消。然后你可能會得出特征對預測沒有影響的結論。通過繪制individual conditional expectation curves而不是aggregated line,我們可以揭示出這種heterogeneous effects。