基於python的隨機森林演算法的實現
阿新 • • 發佈:2021-12-16
基於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:非稀疏資料則預排序,若稀疏資料則不預排序。
一些總結:
- 特徵不能太多,否側效果很差
- 資料集的劃分和分類器的隨機數都要確定,否則每次結果都不相同