基於python的隨機森林算法的實現


隨機森林是一種基於決策樹的算法
它通過從所有特征中隨機抽取m組特征進行決策樹判斷,最終將m個判斷結果綜合起來得出最終的判斷
具體原理自行學習,本文主要着重於python調用sklearn實現random_forest算法進行二分類

首先是對需要用到的函數庫的調用

import numpy as np
from sklearn.preprocessing import MinMaxScaler
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score, GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_auc_score, auc, roc_curve
import matplotlib.pyplot as plt

然后讀取文件和處理數據

rd = pd.read_csv('RadImmune_177.csv')
Radlmmune_177.csv是所有樣本的集合
其中ESTIMATEScore是需要預測的label列
請預先在表格中將label的值設定為0和1,方便后續操作

查看樣本中label分布是否均勻
print(rd.ESTIMATEScore.value_counts())

自動划分數據集為測試集和訓練集

y = rd.ESTIMATEScore #  將rd中的label列讀取至y
x = rd.drop(['ESTIMATEScore', 'ID', 'StromalScore', 'ImmuneScore'], axis=1) # 將rd中不需要的特征列丟掉
seed=0 # 設置一個隨機數種子傳遞給下面的train_test_split函數,否則每次分割出來的訓練集和測試集不一樣
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=seed)

注意:隨機森林做分類預測時對於樣本的特征的值的大小不敏感
且由於隨機取特征取預測,對缺失值也不敏感
可以不用進行特征縮放或均值歸一化

scaler = MinMaxScaler()  # 均值歸一化
x_train = scaler.fit_transform(x_train)
x_test = scaler.fit_transform(x_test)

下面實例化隨機森林分類模型並進行訓練和測試

# random_state參數是隨機取特征時的隨機數,不填此參數每次訓練取得的特征不一樣會導致結果不同
rdc = RandomForestClassifier(random_state=0) 
rdc = rdc.fit(x_train, y_train)
result = rdc.score(x_test, y_test)

繪圖

各個特征的重要性排序及前10表格繪制

importances = rdc.feature_importances_
std = np.std([tree.feature_importances_ for tree in rdc.estimators_], axis=0)
indices = np.argsort(importances)[::-1] # 重要性索引排序
print("Feature ranking:")
for f in range(min(10, x_train.shape[1])):
    print("%2d) %-*s %f" % (f + 1, 30, x_train.columns[indices[f]], importances[indices[f]]))# Plot the feature importances of the forest
plt.figure()
plt.title("Feature importances")
plt.bar(range(10), importances[indices[:10]], tick_label=indices[:10], color="r", align="center")
plt.show()

總體分布情況繪制

f, ax = plt.subplots(figsize=(7, 5))  
ax.bar(range(len(rdc.feature_importances_)), rdc.feature_importances_)  
ax.set_title("Feature Importances")  
plt.show()

ROC分數可視化

predictions_validation = rdc.predict_proba(x_test)[:, 1]
fpr, tpr, _ = roc_curve(y_test, predictions_validation)
roc_auc = auc(fpr, tpr)
plt.title('ROC Validation')
plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()

比較決策樹和隨機森林scores

clf = DecisionTreeClassifier(max_depth=None, min_samples_split=2, random_state=0)
scores = cross_val_score(clf, x_train, y_train)
print(scores.mean())
clf2 = RandomForestClassifier(n_estimators=10, max_depth=None, min_samples_split=2, random_state=0)
scores = cross_val_score(clf2, x_train, y_train)
print(scores.mean())

調整超參數(網格搜索)

最大葉子節點數

param_test1 = {'max_leaf_nodes': range(2, 10, 1)} # 從2-10進行搜索,可自行調整
gsearch1 = GridSearchCV(estimator=RandomForestClassifier(random_state=0,
                                                         class_weight='balanced'), # 使用的分類器參數
                        param_grid=param_test1,  
                        scoring='roc_auc',  
                        cv=5)  
gsearch1.fit(x_train, y_train)
print(gsearch1.best_params_, gsearch1.best_score_)

網格搜索原理就是固定其他的參數,對於選定的參數的范圍每一個都算一遍,找出分數最高的
后面可再進行其他參數的搜索,將前面每一次搜索得到的最好參數放入gsearch2,gsearch3等等分類器中
進行其他參數的搜索,最后的到效果最好的一組參數

分類器參數有哪些
Random Forest Classifier和Random Forest Regressor參數絕大部分相同

- n_estimators: 
也就是弱學習器的最大迭代次數,或者說最大的決策樹個數,默認是10。一般來說n_estimators太小,容易欠擬合,n_estimators太大,  
又容易過擬合,一般選擇一個適中的數值。

- bootstrap:
默認True,是否有放回的采樣。

- oob_score:
默認識False,即是否采用袋外樣本來評估模型的好壞。有放回采樣中大約會有36.8%的數據沒有被采樣到,  
我們常常稱之為袋外數據(Out Of Bag, 簡稱OOB),這些數據沒有參與到訓練集模型的擬合,  
因此可以用來檢測模型的泛化能力。推薦設置為True,因為袋外分數反應了模型擬合后的泛化能力。  
對單個模型的參數訓練,我們知道可以用cross validation(cv)來進行,但是比較消耗時間,  
而且對於隨機森林這種情況沒有太大的必要,所以就用袋外數據對決策樹模型進行驗證,    
類似一個簡單的交叉驗證,性能消耗小,但是效果不錯。

- criterion:
 即CART樹做划分時對特征的評價標准,分類模型和回歸模型的損失函數是不一樣的。

(1)分類RF對應的CART分類樹默認是基尼系數gini,另一個可選擇的標准是信息增益entropy,是用來選擇節點的最優特征和切分點的兩個准則。

(2)回歸RF對應的CART回歸樹默認是均方差MSE,另一個可選擇的標准是絕對值誤差MAE。一般來說選擇默認的標准就已經很好的。

- max_features: 
隨機森林划分時考慮的最大特征數。可以使用很多種類型的值,默認是"None",意味着划分時考慮所有的特征數;  
如果是"log2"意味着划分時最多考慮log2N個特征;如果是"sqrt"或者"auto"意味着划分時最多考慮N−−√N個特征。  
如果是整數,代表考慮的特征絕對數。如果是浮點數,代表考慮特征百分比,即考慮(百分比xN)取整后的特征數,其中N為樣本總特征數。    
一般來說,如果樣本特征數不多,比如小於50,我們用默認的"None"就可以了,如果特征數非常多,  
我們可以靈活使用剛才描述的其他取值來控制划分時考慮的最大特征數,以控制決策樹的生成時間。

- max_depth:
決策樹最大深度。默認為"None",即不限制子樹的深度。這樣建樹時,會使每一個葉節點只有一個類別,或是達到min_samples_split。  
一般來說,數據少或者特征少的時候可以不管這個值。如果模型樣本量多,特征也多的情況下,推薦限制這個最大深度,具體的取值取決於數據的分布。  
常用的可以取值10-100之間。

- min_samples_split:
內部節點再划分所需的最小樣本數,默認2。這個值限制了子樹繼續划分的條件,如果某節點的樣本數小於min_samples_split,則不會繼續划分。  
如果樣本量不大,可以不設置這個值;如果樣本量數量級非常大,則推薦增大這個值。

- min_samples_leaf: 
葉子節點最少樣本數。
這個值限制了葉子節點的最小樣本數,如果某個葉子節點的樣本數小於min_samples_leaf,則會和兄弟節點一起被剪枝。  
默認是1,可以輸入最少的樣本數的整數,或者最少樣本數占樣本總數的百分比。  
如果樣本量不大,不需要管這個值。如果樣本量數量級非常大,則推薦增大這個值。

- min_weight_fraction_leaf: 
葉子節點最小的樣本權重和。這個值限制了葉子節點所有樣本權重和的最小值,
如果小於這個值,則會和兄弟節點一起被剪枝。默認是0,就是不考慮權重問題。  
一般來說,如果我們有較多樣本有缺失值,或者分類樹樣本的分布類別偏差很大,就會引入樣本權重,這時我們就要注意這個值了。

- max_leaf_nodes: 
最大葉子節點數。通過限制最大葉子節點數,可以防止過擬合。默認是"None”,即不限制最大的葉子節點數。  
如果加了限制,算法會建立在最大葉子節點數內最優的決策樹。如果特征不多,可以不考慮這個值,但是如果特征分成多的話,可以加以限制,  
具體的值可以通過交叉驗證得到。

- min_impurity_split: 
節點划分最小不純度。這個值限制了決策樹的增長,如果某節點的不純度(基於基尼系數,均方差)小於這個閾值,則該節點不再生成子節點,即為葉子節點。
一般不推薦改動默認值1e-7。

- splitter: 
隨機選擇屬性"random"還是選擇不純度最大"best"的屬性,建議用默認best。

- presort: 是否對數據進行預分類,以加快擬合中最佳分裂點的發現。默認False,適用於大數據集。  
小數據集使用True,可以加快訓練。是否預排序,預排序可以加速查找最佳分裂點,對於稀疏數據不管用,Bool,auto:非稀疏數據則預排序,若稀疏數據則不預排序。

一些總結:

  1. 特征不能太多,否側效果很差
  2. 數據集的划分和分類器的隨機數都要確定,否則每次結果都不相同

學習自bilibili隨機森林Python實戰


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM