Spark隨機森林模型在互聯網金融上的應用
Spark隨機森林模型在互聯網金融上的應用
之前公司主做現金貸方面的業務,幫忙做了隨機森林的預測風險模型,模型的應用場景主要是互聯網金融對風險的評估,由於隨機森林採用「集成學習」的方法,利用節點分裂進行決策,模型穩定性較好,通過低方差防止過擬合,對雜訊的容忍度也相對較好。
這篇文章大概簡單介紹下相關思路,不過不會涉及到具體實驗數據。
一、 隨機森林原理
隨機森林(Random Forest, RF)是統計學家Breiman提出的一種分類組合器方法,其元分類器利用分類回歸樹,用Bagging方法製造有差異的訓練樣本集,並且在構建單棵樹時,隨機地選擇特徵對內部節點進行屬性分裂。由多個分類決策樹組成的分類器,每一個分類器中採用的獨立同分布的隨機向量決定了樹的生長過程,最終是由所有的樹的多數表決結果來決定最後模型的輸出結果。 演算法如下:
1. 從樣本集中用Bootstrap採樣選出n個樣本;隨機選擇訓練樣本子集,也就是多次有放回抽樣形成基分類器的訓練集。
2. 從所有屬性中隨機選擇k個屬性,選擇最佳分割,屬性作為節點建立CART決策樹;這種抽取隨機抽取特徵子集,也就是在每次考量特徵的重要性之前是基於隨機抽取的特徵集合。
3. 重複以上兩步m次,即建立了m棵CART決策樹,這裡決策樹只需要自由生長,不需要進行剪枝。
隨機森林有兩種不同的抽樣方法:
1. 無權重抽樣,也叫 bagging 方法,是一種用來提高學習演算法準確度的方法。bagging 法是以可重複的隨機抽樣為基礎的,每個樣本是初始數據集有放回抽樣。在可重複抽樣生成多個訓練子集時,存在於初始訓練集 D中的所有的樣本都有被抽取的可能,但在重複多次後,總有一些樣本是不能被抽取的,每個樣本不能被抽取的概率為
N為原始訓練樣本數。
2. 更新權重抽樣,就是 boosting 方法,也叫更新權重抽樣。Boosting 方法進行抽樣時,首先隨機抽樣產生一組訓練集,然後對這組訓練集中的每一個訓練集設定權重為1/n,n 為訓練集中樣本的個數,在設定權重後,對每個帶權重的訓練集進行測試,在每次測試結束後,對分類性能差的訓練集的權重進行提升,從而產生一個新的權重系列,經過多次訓練後,每個訓練集就有一個和其相對應的權重,在投票時,這些權重就可以對投票的結果產生影響,從而影響最終的決策結果。
二、 平衡樣本
在實際應用中,會大量碰到一些樣本不平衡的情況。如欺詐用戶(「羊毛黨」)只佔用戶群體的1/40以下,或者對於老用戶來說,大多數會準時還款,只有少部分會長期逾期,因此需要平衡正負樣本。
目前數據挖掘領域會採用代價敏感學習來解決樣本不平衡問題,少量樣本(如醫療檢測里的「病變」樣本)的學習代價會更高,通過給予不同類別的樣本不同的錯誤分類的懲罰因子來區分上述兩種誤分。也就是說,可以對數量小的樣例(「大題目」)的誤分施加更嚴厲的懲罰而對數量大的樣例(「小題目」)的誤分採取較為寬鬆的懲罰措施。
我在工程中一般傾向於採取Smote演算法,通過Python實現,區分出訓練數據和測試數據,訓練數據通過過採樣方法達到樣本平衡。SMOTE方法是一種經常被採用的過採樣方法,它是一種人工合成新樣本的技術。這種方法會隨機挑選出少量類樣本中的樣本點,然後取到它的 K-近鄰的正類樣本中的任意一個樣本點,在這兩個點的距離度量的中間位置生成一個新的樣本點,從而達到擴展正類樣本的目的。
演算法流程如下:
Step 1 為每個負類樣本挑選出 K
個數量的鄰近樣本;Step 2 將負類樣本和其鄰近樣本進行線性組合;
Step 3 將組合產生新的「人造」樣本加入到原數據集中;
Step 4 計算數據集的非平衡率,當數據集沒有達到目標平衡率時,轉到Step 1,否則程序結束。
當然,「天下沒有免費的午餐」, Smote演算法也有一定局限性:
1、 用K近鄰進行過採樣本來就有一定盲目性。
2、 它無法克服非平衡數據集的數據分布問題,容易產生分布邊緣化問題。由於少量樣本的分布決定了其可選擇的近鄰,如果這個少量樣本本身處在自己樣本集的分布邊緣,則由此及衍生的相鄰樣本產生的「人造」樣本也會處在這個邊緣,且會越來越邊緣化,從而模糊了正類樣本和負類樣本的邊界,而且使邊界變得越來越模糊。
三、 特徵選擇
一般為了從大數據給用戶畫像,用戶的原始特徵可能有上百個(從年齡、地域到芝麻信用分數),冗餘的特徵會造成過擬合,我自己在工程上傾向於採取兩種方法:
1、 PCA(主成分提取分析):R和Python有現成的PCA分析的代碼,不過為了確定權重重要性,可以自己寫代碼對特徵值大小進行排序。
2、 Boruta(R語言進行特徵選擇的利器):Boruta是一種特徵選擇演算法。精確地說,它是隨機森林周圍的一種包裝演算法。這個包的名字來源是斯拉夫神話中一個居住在松林的惡魔。
Boruta演算法步驟如下:
Step 1 首先,它通過創建混合副本的所有特徵(即陰影特徵)為給定的數據集增加了隨機性。
Step 2 然後,它訓練一個隨機森林分類的擴展數據集,並採用一個特徵重要性措施(默認設定為平均減少精度),以評估的每個特徵的重要性,越高則意味著越重要。
Step 3 在每次迭代中,它檢查一個真實特徵是否比最好的陰影特徵具有更高的重要性(即該特徵是否比最大的陰影特徵得分更高)並且不斷刪除它視為非常不重要的特徵。
Step 4最後,當所有特徵得到確認或拒絕,或演算法達到隨機森林運行的一個規定的限制時,演算法停止。
代碼也很簡單:
library(Boruta)
data
<- read.csv("xxx.csv");data2
<-na.omit(data);model<-Boruta(data2$credit_status~.,
data=data2, doTrace = 2)print(model$finalDecision)
得到的結果會告知哪些特徵予以保留。
四、 Spark隨機森林訓練模型
目前Spark有兩個庫分別支持隨機森林模型(ML,Mllib),同時,模型分成進行決策的隨機森林決策樹和隨機森林回歸樹。
Mllib庫的隨機森林模型對RDD數據或JavaRDD數據進行操作,決策結果不支持輸出概率,靠模糊矩陣(Confusion Matrix)分別計算正樣本、負樣本的準確率和召回率判斷模型的效果。
ML庫的隨機森林模型則對Dataset<Row>進行操作,決策結果支持輸出概率,在目前國家採取限制年利率政策出台背景下,概率模型調整閾值可以控制壞賬率,通過AUC值計算可以判定模型效果。此外,ML庫可以採用ParamMap類進行實例化設置參數,進入到PipeLine的並行模型存儲介面,通過CrossValidator設置K折驗證,得到最優結果。然而,以個人經驗,在模型演算法已知的情況下,特徵選擇和樣本劃分對於數據的影響,遠比花費一天時間在伺服器上調參數帶來的提升要大。
按照Spark官網的解釋,有五個參數需要注意:
http://spark.apache.org/docs/latest/mllib-ensembles.html#classification
numTrees:隨機森林元分類器(基分類器數目),樹的數量提升有助於提高預測精度,但一般接近一千棵左右,精度會達到收斂。
maxDepth:隨機森林的最大深度,提高這個值有助於改善預測精度,但會增加訓練時間,且容易造成過擬合。然而,即使如此,隨機森林各棵樹之間的弱相關特性使得其對過擬合的魯棒性好於決策樹(Decision Tree)。
maxBins:特徵的最大箱數,即連續特徵離散化的最大數量,以及選擇每個節點分裂特徵的方式。
featureSubsetStrategy:每次分裂候選特徵數量,一般選默認值「auto」,這個值應該接近於輸入特徵值的平方根。
impurity:計算信息增益的準則,根據基尼係數(「gini」)還是信息熵(「entropy」)進行計算。
這是目前spark官方的調用例子:
五、 目前的局限性
我們知道,隨機森林是採取Bagging方法進行抽樣的,每個樣本是初始數據集有放回抽樣。在可重複抽樣生成多個訓練子集時,存在於初始訓練集 D中的所有的樣本都有被抽取的可能,但在重複多次後,總有一些樣本是不能被抽取的,每個樣本不能被抽取的概率為:
當N足夠大的時候,概率收斂於自然對數的倒數1/e,這個數據說明,有將近 37%的樣本不會被抽出來,這些不能從初始數據集中抽取出來的樣本組成的集合,稱之為袋外數據,簡記為 OOB。使用 OOB數據來估計隨機森林演算法的泛化能力,稱之為 OOB 估計。以每一棵決策樹為單位, 利用未被該森林選中的所有的訓練樣本點的集合,統計該樹的 OOB 誤分率;將所有樹的誤分率取平均得到隨機森林的 OOB 誤分率,就可以得到一個 OOB 誤差估計,OOB誤差估計在統計學上是一個無偏估計。
目前,R語言的機器學習包和Python的機器學習包都支持了隨機森林演算法的OOB估計修正版。然而,Spark框架尚不支持,因此,對於提高模型精度來說,依然有改進空間。不過大多數公司重視快速迭代,而「二次開發」是需要一定時間成本的,暫時沒有去支持這個演算法。
推薦閱讀:
※面壁者系列:線性回歸
※《大演算:機器學習的終極演演算法將如何改變我們的未來,創造新紀元的文明》
※微分方程和矩陣指數【MIT線代第二十三課】
※如何正確使用「K均值聚類」?
TAG:機器學習 |