隨機森林的直觀理解

對於那些認為隨機森林是黑匣子演算法的人來說,這篇帖子會提供一個不同的觀點。接下來,我將從4個方面去理解隨機森林模型。

1.我們的特徵有多重要?

在sklearn隨機森林中使用model.feature_importance來研究其重要特徵是很常見的。重要特徵是指與因變數密切相關的特徵,並且對因變數的變化影響較大。我們通常將儘可能多的特徵提供給隨機森林模型,並讓演算法反饋對預測最有用的特徵列表。但仔細選擇正確的特徵可以使我們的目標預測更加準確。

計算feature_importances的想法很簡單,但卻很有效。

把想法分解成簡單的幾步:

  1. 訓練隨機森林模型(假定有正確的超參數)
  2. 找到模型的預測分數(稱之為基準分數)
  3. 多次(p次,p為特徵個數)計算預測分數,每次打亂某個特徵的順序,可見下圖
  4. 將每次預測分數與基準分數進行比較。如果隨機調整特徵順序後預測分數小於基準分數,這意味著我們的模型如果沒有這個特徵會變得很糟糕。
  5. 刪除那些不會降低基準分數的特徵,並用減少後的特徵子集重新訓練模型。

圖1:計算特徵重要性

註:將F4列打亂重新進行預測來判斷特徵F4的重要性

計算特徵重要性的代碼:

下面的代碼將為所有特徵提供一個結構為{特徵,重要性}的字典。

# defining rmse as scoring criteria (any other criteria can be used in a similar manner) def score(x1,x2): return metrics.mean_squared_error(x1,x2)# defining feature importance function based on above logic def feat_imp(m, x, y, small_good = True): """m: random forest modelx: matrix of independent variablesy: output variablesmall__good: True if smaller prediction score is better""" score_list = {} score_list[『original』] = score(m.predict(x.values), y) imp = {} for i in range(len(x.columns)): rand_idx = np.random.permutation(len(x)) # randomization new_coli = x.values[rand_idx, i] new_x = x.copy() new_x[x.columns[i]] = new_coli score_list[x.columns[i]] = score(m.predict(new_x.values), y) imp[x.columns[i]] = score_list[『original』] — score_list[x.columns[i]] # comparison with benchmark if small_good: return sorted(imp.items(), key=lambda x: x[1]) else: return sorted(imp.items(), key=lambda x: x[1], reverse=True)

圖2:隨機森林中的重要特徵圖2:隨機森林中的重要特徵

輸出:

importance = feat_imp(ens, X_train[cols], y_train); importance[("YearMade", -0.21947050888595573), ("Coupler_System", -0.21318328275792894), ("ProductSize", -0.18353291714217482), ("saleYear", -0.045706193607739254), ("Enclosure", -0.041566508577359523), ("MachineID", -0.01399141076436905), ("MachineHoursCurrentMeter", -1.9246700722952426e-05)]在上面的輸出中,可以看出,YearMade將最大程度增加RMSE預測。所以它一定是最重要的特徵。(上面的結果所對應的數據是從Kaggle competition獲取的,這是鏈接——https://www.kaggle.com/c/bluebook-for-bulldozers)

2.我們對我們的預測有多大信心?

一般來說,當企業想要有所預測時,他們的最終目的不是降低成本就是提高利潤。在做出重大商業決策之前,企業十分熱衷於去評估做出這個決定的風險的大小。但是,當預測結果並沒有被展現在置信區間時,我們可能會無意中將企業至於更多的風險中,而不是降低風險。

當我們使用線性模型(基於分布假設的一般模型)時,比較容易找到我們預測的置信水平。但是當談到隨機森林的置信區間時,找起來並不是那麼容易。

圖3:偏差與方差的說明圖

我想,任何上過線性回歸課程的人都肯定看過這張圖3。為了找到一個最佳線性模型,我們要去尋找偏差—方差最為折衷的模型。這張圖片很好地說明了預測中偏差和方差的定義。(我們理解為這4張圖分別是由四個不同的人擲飛鏢所得)。

如果我們有高偏差和低方差值時(第三個人),我們投擲的飛鏢會固定的遠離紅心。相反,如果我們有高的方差和低的偏差(第二個人),那麼他投擲飛鏢的結果就很不一樣。如果有人去猜測他下一個飛鏢擊中的位置,那麼它既有可能打到靶心也有可能遠離靶心。現在我們來假設在現實生活中識別一起信用欺詐等同於上面例子擊中靶心。如果信用公司擁有的的預測模型與上面第二人的擲飛鏢行為很相似,那麼該公司在大多數時候都不會抓住這個詐騙犯,儘管模型預測的是正確的。

因此,不僅僅是意味著預測的準確程度,我們還應該檢查我們的預測的置信水平。

在隨機森林中如何做到這一點?

隨機森林是由許多決策樹組成。每棵樹分別預測新的數據,隨機森林從這些樹中提取出平均預測值。預測置信水平的想法只是為了去看來自不同樹木的預測有多少因為新的觀測而產生變化,然後進一步分析。

基於方差樹預測置信度的源代碼:

#Pseudo code: def pred_ci(model, x_val, percentile = 95, n_pnt): """ x_val = validation input percentile = required confidence level model = random forest model """ allTree_preds = np.stack([t.predict(x_val) for t in model.estimators_], axis = 0) err_down = np.percentile(allTree_preds, (100 - percentile) / 2.0 ,axis=0) err_up = np.percentile(allTree_preds, 100- (100 - percentile) / 2.0 ,axis=0) ci = err_up - err_downyhat = model.predict(x_val) y = y_val df = pd.DataFrame() df["down"] = err_down df["up"] = err_up df["y"] = y df["yhat"] = yhat df["deviation"] = (df["up"] - df["down"])/df["yhat"] df.reset_index(inplace=True) df_sorted = df.iloc[np.argsort(df["deviation"])[::-1]] return df_sorted註:偏差 = (up-down)/Yhat

以上代碼的輸出如下所示:

圖4:基於方差樹的置信樹圖

從這個輸出數據可以讀出,我們可以說我們對於驗證集上索引為14的觀測的預測最沒有信心。

3.什麼是預測路徑?

如果我們想要分析哪些特徵對於整體隨機森林模型是重要的,則 特徵重要性(如在第一部分中)是有用的。但是如果我們對某個特定的觀察感興趣,那麼 Tree interpreter的角色就會發揮作用。

舉個例子,現在有一個RF模型,這種模型會預測—一位來醫院的患者X是否具有很高的概率再入院?,為了簡單起見,我們考慮只有3個特徵—患者的血壓值,患者的年齡以及患者的性別。現在,如果我們的模型認為患者A有80%的可能會再次入院,我們怎麼能知道這個被模型預測為他(她)將重新入院的患者A有什麼特殊之處?在這種情況下,Tree interpreter會指示預測路徑緊隨那個特殊的患者。就像是,因為患者A是65歲的男性,這就是為什麼我們的模型會預測他將再次入院。另一個被模型預測將再次入院的患者B ,可能時因為他有高血壓(而不是因為年齡或性別)。

基本上,Tree interpreter給出了偏差的排序列表(在起始節點的平均值)以及單個節點對給定預測的貢獻。

圖5:決策樹路徑(來源:http://blog.datadive.net/interpreting?random?forests/)

圖5的這棵決策樹(深度:3層)基於波士頓房價數據集。根據中間節點的預測值以及導致數值發生變化的特徵,它顯示了決策路徑的分解。單節點的貢獻是該節點的值與前一個節點值的差值。

圖6:Tree interpreter(最終再次入院的概率=0.6)

圖6 給出了對於患者A使用Tree interpreter的輸出示例。圖片顯示年齡為65歲是模型預測再入院概率高於均值的最高貢獻者。

圖7:將特徵貢獻通過瀑布圖可視化展示圖

圖6同樣也可以使用瀑布圖7來表示。我從「 瀑布圖包 」中選材做的這個快速簡單的瀑布圖。

上面的瀑布圖可視化代碼:

from waterfallcharts import quick_charts as qca = ["Bias", "Age", "Sex", "Blood Pressure"]b = [0.3, 0.6, -0.1, -0.2]plot = qc.waterfall(a,b, Title= "Patient A", y_lab= "Predicted probability", x_lab= "Contributing features (path)", net_label = "Final Prediction")plot.show()

相關變數的闡釋:

? 值(圖片B)是指通過節點預測目標值。(就是在該節點中落下的觀測目標的平均值)。

? 貢獻是當前節點的值減去上一節點的值(這是為一個路徑提供的貢獻特徵)。

? 路徑是為了到達葉節點而通過某些觀察所獲得的所有特徵分割的組合。

tree interpreter包直接用來計算每個節點的貢獻,鏈接:treeinterpreter

4.目標變數如何與重要特徵相關? Partial Dependence Plots

找到最重要的特徵後,下一步我們可能會感興趣的是研究目標變數與興趣特徵之間的直接關係。從線性回歸中得到的與其相類似的是模型係數。對於線性回歸,係數以這種方式被計算,即我們可以通過說:「在Xj中有1個單位變化,保持所有其他Xi不變,Y會發生什麼變化?」這樣的方式來解釋。

雖然我們有來自隨機森林的特徵重要性,但是它們只是給出Y的變化是由於Xi的改變之間的相關性。我們不能直接地解釋他們就像保持所有其他特徵不變,Y該變數取決於Xj中的單位的變化。

幸運的是,我們有看一被看作線性模型係數圖表的局部依賴圖,但同樣也可被擴展為看起來像黑箱模型。這個想法是將預測中所做的改變孤立於一個特定的功能。它不同於X對Y的散點圖,因為散點圖不能隔離X對Y的直接關係,並且可能受X和Y所依賴的其他變數的間接關係所影響。

PDP分析步驟如下:

  1. 訓練一個隨機森林模型(假設F1 … F4是我們的特徵,Y是目標變數,假設F1是最重要的特徵)。
  2. 我們有興趣探索Y和F1的直接關係。
  3. 用F1(A)代替F1列,並為所有的觀察找到新的預測值。採取預測的平均值。(稱之為基準值)
  4. 對F1(B)… F1(E)重複步驟3,即針對特徵F1的所有不同值。
  5. PDP的X軸具有不同的F1值,而Y軸是雖該基準值F1值的平均預測而變化。

圖8:PDP分析邏輯圖

圖 9 是partial dependence plot的一個例子。數據來自 kaggle bulldozer competition data,它顯示了生產年份(YearMade)和(銷售價格)SalesPrice的關係

圖9:partial dependence plot(YearMade與SalePrice的變化)

而圖10是SalePrice與YearMade的線狀圖。我們可以看到,散點圖/折線圖可能無法像PDP那樣捕獲YearMade對SalesPrice的直接影響。

圖10:上述兩個圖片均來自(來源https://github.com/fastai/fastai/tree/master/courses/ml1)

寫在最後:

在大多數情況下,隨機森林在預測中可以擊敗線性模型預測。針對隨機森林經常提出的反對意見是:對它的理解沒有線性模型那樣直觀,但是本文的討論希望幫助你回答這樣的反對意見。

作者個人簡歷:目前在舊金山大學學習數據科學(分析),在Manifold.ai做實習生。此前,曾在凱捷諮詢公司擔任數據科學家,在Altisource擔任高級業務分析師。


您可到BigQuant查看原文並參與討論:隨機森林的直觀理解

更多精彩文章您可前往BigQuant社區進行查看

加入 人工智慧量化投資交流群:微信搜索bigq100,添加微信群管理員微信,附上姓名、所在機構、部門和職位,審核後管理員會邀請您入群。

關注 BigQuant 微信公眾號:微信搜索 BigQuant, 獲取更多人工智慧、Machine Learning、量化投資相關文章。


推薦閱讀:

美日巨型機器人已經運達決戰現場!希望誰贏呢?
AI晶元四大流派論劍,中國能否彎道超車?|半導體行業觀察
大家來預測一下吳恩達三個新項目之一deeplearning.ai之後,接下來的兩個項目將會是什麼項目?
錯過了這次影響全行業的語音智能峰會?這篇文章或許還能搶救一下 | WARE 2017
谷歌人工智慧唇讀術完虐人類,僅憑5千小時電視節目!人類古老的技藝再次淪陷

TAG:机器学习 | 人工智能 |