一、定義
????????隨機森林是一種有監(jiān)督學習算法,是以決策樹為基學習器的集成學習算法。????????
????????那什么是有監(jiān)督學習呢?有監(jiān)督學習就是把有已知結果的數(shù)據(jù)集拿去訓練,如果訓練結果與標準答案的精度足夠高就可以使用這個模型去預測或者分類未知結果的數(shù)據(jù)集。簡單來說就是你寫很多有標準答案的試卷,當你的準確率足夠高的時候你就可以去寫沒有標準答案的試卷了,因為如果你平時都能考全國前三,那你高考就大概率能考到全國前三。有監(jiān)督學習主要應用于分類和回歸。
????????無監(jiān)督學習的數(shù)據(jù)是沒有已知結果的數(shù)據(jù),比如清北大學自主招生考試,學校事先不知道學生平時的考試結果,但是有學生奧數(shù)經歷的介紹,根據(jù)以往經驗奧數(shù)高的一般考的就好,就收了,但是不排除奧數(shù)好但是成績不行的學生存在。無監(jiān)督學習主要用于聚類和降維。
?????????集成學習故名思義就是“組合學習”,比如本文介紹的隨機森林算法就是由很多個決策樹組成的算法,假設有A、B兩個選擇,100個決策樹一起投票,超過50個樹投給了A那么隨機森林的結果就是A。
二、模型理論
? ? ? ? ? 傳統(tǒng)的決策樹模型在訓練時經常會出現(xiàn)過擬合的情況,隨機森林是有效解決該問題的方法之一。隨機森林本質上是很多樹的組合,并且每一棵樹因為取的樣本略有不同所以樹與樹之間也是有所區(qū)別的。
? ? ? ? 隨機森林的思想是每棵樹的預測效果可能都相對較好但可能對部分數(shù)據(jù)過擬合,如果構造足夠多的樹,并且每棵樹都可能有很好的預測結果但是也都會對不同的部分數(shù)據(jù)過擬合,我們可以通過取平均值來降低過擬合同時保證模型精度,這在數(shù)學上是被證明過的。
? ? ? ??隨機森林的隨機性體現(xiàn)在兩個方面,一個是特征隨機性,一個是樣本隨機性。先隨機抽取足夠的樣本,再根據(jù)這批樣本選擇最好的特征,這樣每棵樹的特征實際上都有可能不完全一樣。因為隨機性,森林的偏向可能會略有增加,但是因為取平均,它的方差也會減小,從而生成一個更好的模型。
算法過程如下:
(1)、通過有放回抽樣的方法隨機抽取n個樣本作為決策樹模型的樣本
(2)、假設這些樣本有M個特征,隨機選擇m個特征作為該決策樹的分裂屬性
(3)、重復(1)(2)n次就會生成n個決策樹,這樣就構成了隨機森林,這些決策樹的投票結果就是隨機森林的結果。? ? ? ??
三、優(yōu)缺點
優(yōu)點:
(1)、可以處理很高維度(特征很多)的數(shù)據(jù),并且不用降維,不用做做特征選擇
(2)、對數(shù)據(jù)集的適應能力強,既適用于離散型也適用于連續(xù)型數(shù)據(jù)
(3)、它可以判斷特征的重要程度,篩選出重要特征,并且篩選結果也可以用于其他模型,是非常流行的特征篩選方法
(4)、由于采用集成算法,精度往往比單個模型的精度高
(5)、實現(xiàn)簡單、精度高,不容易過擬合,可以作為基準模型
缺點:
(1)、隨機森林已經被證明在某些噪音較大的分類或回歸問題上會過擬合
(2)、對于有不同取值的屬性的數(shù)據(jù),取值劃分較多的屬性會對隨機森林產生更大的影響,所以隨機森林在這種數(shù)據(jù)上產出的屬性權值是不可信的
四、參數(shù)介紹???????
?????????n_estimators :樹的數(shù)量,默認是10,就是你準備在你的森林里種多少樹。這個參數(shù)是最重要的,樹的數(shù)量決定了最后的準確性,但是也會讓你的運行速度變的很慢,所以需要不斷的測試去決定。
? ???????max_features:隨機森林允許單個決策樹使用特征的最大數(shù)量。
? ? ? ? ?Auto/None/sqrt :簡單地選取所有特征,每顆樹都可以利用他們。這種情況下,每顆樹都沒有任何的限制。默認是auto
? ? ? ? ? ? ? ? int:是整數(shù) ??
? ? ? ? ? ? ? ? float:百分比選取
? ? ? ? ? ? ? ? log2:所有特征數(shù)的log2值
? ? ? ? criterion : criterion:分裂節(jié)點所用的標準,可選“gini”, “entropy”,默認“gini”。
? ? ? ? max_depth:樹的最大深度。如果為None,則將節(jié)點展開,直到所有葉子都是純凈的(只有一個類),或者直到所有葉子都包含少于min_samples_split個樣本。默認是None
? ? ? ? ?min_samples_split:拆分內部節(jié)點所需的最少樣本數(shù):如果為int,則將min_samples_split視為最小值。如果為float,則min_samples_split是一個分數(shù),而ceil(min_samples_split * n_samples)是每個拆分的最小樣本數(shù)。默認是2
? ? ? ? min_samples_leaf:在葉節(jié)點處需要的最小樣本數(shù)。僅在任何深度的分割點在左分支和右分支中的每個分支上至少留下min_samples_leaf個訓練樣本時,才考慮。這可能具有平滑模型的效果,尤其是在回歸中。如果為int,則將min_samples_leaf視為最小值。如果為float,則min_samples_leaf是分數(shù),而ceil(min_samples_leaf * n_samples)是每個節(jié)點的最小樣本數(shù)。默認是1。
? ? ?最主要的兩個參數(shù)是n_estimators和max_features,n_estimators理論上是越大越好,但是計算時間也相應增長,所以預測效果最好的值將會出現(xiàn)在合理的樹個數(shù);max_features每個決策樹在隨機選擇的特征里找到某個“最佳”特征,使得模型在該特征的某個值上分裂之后得到的收益最大化。max_features越少,方差就會減少,但同時偏差就會增加。如果是回歸問題則max_features=n_features,如果是分類問題,則max_features=sqrt(n_features),其中,n_features 是輸入特征數(shù)。 ? ? ? ?
????????從下圖中我們可以看到參數(shù)對Random Forest的影響:
? ? ? ? 可以看到除了n_estimators外其余參數(shù)理論上都不是越大越好,包括?n_estimators實際中也不是越大越好,那如何調節(jié)出好的參數(shù)呢,一個一個試是不可能的,機器學習庫提供了一個暴力調參的函數(shù)GridSearchCV(網格搜索),但是這個函數(shù)很容易讓你的電腦爆炸,因為如果4個參數(shù)一起調,每個參數(shù)都是100種可能,那就會運行100x100x100x100次模型,顯然這是不行的,但是我們可以通過貪心算法,即把最重要的兩個參數(shù)放到GridSearchCV里找到最優(yōu)參數(shù),再把次要的參數(shù)放進去遍歷??傊?,不斷的嘗試就對了。
五、案例數(shù)據(jù)簡介
?????????數(shù)據(jù)集中共有24個特征,7000個樣本,從Y的值為0和1可以知道是二分類問題。這是比賽數(shù)據(jù),非保密數(shù)據(jù),只是我不知道怎么打包上傳,如果有需要可以私信我。
六、案例建模及具體步驟
讀取數(shù)據(jù)
import pandas as pd
datas=pd.read_csv('data_20221030(1).csv')
datas=datas[datas.columns[2:]]
datas
????????數(shù)據(jù)如上面的截圖所示??
計算皮爾遜相關系數(shù)
plt.figure(figsize=(20,20))
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
sns.heatmap(discreat_data.corr(),cmap="YlGnBu",annot=True)
plt.title("相關性分析圖")
????????想關性分析可以初步篩掉一些與Y相關性很低的特征,此處的皮爾遜相關系數(shù)其實適用于連續(xù)型數(shù)據(jù),離散型數(shù)據(jù)用肯達爾相關系數(shù)和斯皮爾曼相關系數(shù)會更好一點。
這里僅演示沒有篩指標也沒有用其他兩個相關系數(shù),相關系數(shù)的介紹可以參考這里:
- (59條消息) 相關性分析、相關系數(shù)矩陣熱力圖_最后一瓢若水的博客-CSDN博客_相關系數(shù)矩陣熱力圖
劃分訓練集和測試集
x=datas.iloc[:,:-1]#包含9月還款和消費狀態(tài)
y=datas['Y']
X_train, X_test, y_train, y_test = train_test_split(x, y, random_state=90)
????????random_state是隨機數(shù)種子,相同的隨機數(shù)種子可以保證抽取相同的樣本,如果不設定種子,下一次跑代碼的時候用來訓練的樣本就會和上一次的不一樣。
導入模塊和庫
#隨機森林
#導入所需要的包
from sklearn.metrics import precision_score
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report#評估報告
from sklearn.model_selection import cross_val_score #交叉驗證
from sklearn.model_selection import GridSearchCV #網格搜索
import matplotlib.pyplot as plt#可視化
import seaborn as sns#繪圖包
from sklearn.preprocessing import StandardScaler,MinMaxScaler,MaxAbsScaler#歸一化,標準化
# 忽略警告
import warnings
warnings.filterwarnings("ignore")
默認參數(shù)下的隨機森林及結果?
model=RandomForestClassifier()#建立默認參數(shù)的模型
# 訓練模型
model.fit(X_train,y_train)
# 預測值
y_pred = model.predict(X_test)
'''
評估指標
'''
# 求出預測和真實一樣的數(shù)目
true = np.sum(y_pred == y_test )
print('預測對的結果數(shù)目為:', true)
print('預測錯的的結果數(shù)目為:', y_test.shape[0]-true)
# 評估指標
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('預測數(shù)據(jù)的準確率為: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('預測數(shù)據(jù)的精確率為:{:.4}%'.format(precision_score(y_test,y_pred)*100))
print('預測數(shù)據(jù)的召回率為:{:.4}%'.format(recall_score(y_test,y_pred)*100))
print('預測數(shù)據(jù)的F1值為:',f1_score(y_test,y_pred))
print('預測數(shù)據(jù)的Cohen’s Kappa系數(shù)為:',cohen_kappa_score(y_test,y_pred))
# 打印分類報告
print('預測數(shù)據(jù)的分類報告為:','\n',classification_report(y_test,y_pred))
?????????默認參數(shù)跑出來的準確率達到了80%,說實話也就一般,下面我們進行簡單調參,看看能否把準確率往上調一點。
七、調節(jié)參數(shù)
? ? ? ?這里我會用GridSearchCV(網格搜索)對單個參數(shù)進行遍歷,看看單個最好的參數(shù),組合到一起是否能把準確率往上提一點,當然這樣很容易陷入局部最優(yōu)的陷阱,也可以把最重要的兩個參數(shù)組合遍歷,再對單個參數(shù)進行遍歷。調參是個很耗時的過程,所以這里以演示幫助理解為主,僅遍歷單個參數(shù)。
n_estimators ?‘種樹’(樹的數(shù)量)
#n_estimators 學習曲線
scorel = []
for i in range(0,200,10):
model = RandomForestClassifier(n_estimators=i+1,
n_jobs=-1,
random_state=90).fit(X_train,y_train)
score = model.score(X_test,y_test)
scorel.append(score)
print(max(scorel),(scorel.index(max(scorel))*10)+1) #作圖反映出準確度隨著估計器數(shù)量的變化,71的附近最好
plt.figure(figsize=[20,5])
plt.plot(range(1,201,10),scorel)
plt.show()
可以看到最優(yōu)的‘樹量’是在71附近,我們在縮小范圍看一下。
## 根據(jù)上面的顯示最優(yōu)點在71附近,進一步細化學習曲線
scorel = []
for i in range(60,80):
RFC = RandomForestClassifier(n_estimators=i,
n_jobs=-1,
random_state=90).fit(X_train,y_train)
score = RFC.score(X_test,y_test)
scorel.append(score)
print(max(scorel),([*range(60,80)][scorel.index(max(scorel))])) #76是最優(yōu)的估計器數(shù)量
plt.figure(figsize=[20,5])
plt.plot(range(60,80),scorel)
plt.show()
最優(yōu)的‘樹量’是76。
max_depth ?優(yōu)化
scorel = []
for i in range(3,30):
RFC = RandomForestClassifier(max_depth=i,n_estimators=76,
n_jobs=-1,
random_state=90).fit(X_train,y_train)
score = RFC.score(X_test,y_test)
scorel.append(score)
print(max(scorel),([*range(3,30)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(3,30),scorel)
plt.show()
樹的最大深度(max_depth)默認可以不輸入,在數(shù)據(jù)量較大或者特征較多的時候可以限制在10-100之間避免模型太復雜導致過擬合,如果數(shù)據(jù)量較小或特征不多的情況下是可以不輸入的,比如此處數(shù)據(jù)量也不是很大,可以不用調整。
?min_samples_leaf ? 優(yōu)化
scorel = []
for i in range(1,20):
RFC = RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=i,
n_jobs=-1,
random_state=90).fit(X_train,y_train)
score = RFC.score(X_test,y_test)
scorel.append(score)
print(max(scorel),([*range(1,20)][scorel.index(max(scorel))]))
plt.figure(figsize=[20,5])
plt.plot(range(1,20),scorel)
plt.show()
?max_features ?優(yōu)化
## 調整max_features
param_grid = {'max_features':['auto', 'sqrt','log2']}
RFC = RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=1,min_samples_split=7
)
GS = GridSearchCV(RFC,param_grid,cv=10)
GS.fit(X_train,y_train)
print(GS.best_params_ ) #最佳最大特征方法為sqrt
print(GS.best_score_)
criterion ? 優(yōu)化
param_grid = {'criterion':['gini', 'entropy']}
RFC = RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=1,min_samples_split=7,max_features='sqrt')
GS = GridSearchCV(RFC,param_grid,cv=10)
GS.fit(X_train,y_train)
print(GS.best_params_ )
print(GS.best_score_)
min_samples_leaf ?優(yōu)化
param_grid = {'min_samples_leaf':np.arange(1, 11, 1)}
RFC = RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=1,min_samples_split=7,max_features='sqrt',criterion='entropy')
GS = GridSearchCV(RFC,param_grid,cv=10)
GS.fit(X_train,y_train)
print(GS.best_params_ )
print(GS.best_score_)
?
????????可以看到就這樣一步一步調也把準確度提高了差不多3%,但是這里調的很簡陋,還有很多組合調參的方式值得一一嘗試。
隨機森林-特征篩選
? ? ? ? 我們用RandomForestClassifier自帶的特征重要性函數(shù),看一下哪些是重要特征,剔除掉非重要特征,看看效果會不會有提升。
feat_labels = datas.columns[:-1]
# n_jobs 整數(shù) 可選(默認=1) 適合和預測并行運行的作業(yè)數(shù),如果為-1,則將作業(yè)數(shù)設置為核心數(shù)
RFC= RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=2,min_samples_split=7,max_features='sqrt',criterion='entropy',
random_state=0, n_jobs=-1)
forest.fit(X_train, y_train)
labe_name=[]
imports=[]
# 下面對訓練好的隨機森林,完成重要性評估
# feature_importances_ 可以調取關于特征重要程度
importances = RFC.feature_importances_
print("重要性:",importances)
x_columns =datas.columns[:-1]
indices = np.argsort(importances)[::-1]
for f in range(X_train.shape[1]):
# 對于最后需要逆序排序,我認為是做了類似決策樹回溯的取值,從葉子收斂
# 到根,根部重要程度高于葉子。
print("%2d) %-*s %f" % (f + 1, 30, feat_labels[indices[f]], importances[indices[f]]))
labe_name.append(feat_labels[indices[f]])
imports.append(importances[indices[f]])
# 構造數(shù)據(jù)
a = pd.DataFrame({"feature": labe_name})
b = pd.DataFrame({"importance": imports})
df = pd.concat([a, b], axis=1)
#作圖
sns.barplot(x="importance", y="feature", data=df, order=df["feature"], orient="h")
文章來源:http://www.zghlxwxcb.cn/news/detail-415254.html
?????????根據(jù)排序結果我嘗試剔除了SEX、MARRIAGE、EDUCATION三個特征跑了上面訓練好的模型,但是效果并沒有提升,所以就不展示了,不過隨機森林的特征篩選是可以應用到其他模型上的,另外訓練隨機森林模型時特征輸入順序不一樣,得到的結果也會略有差異,但是同為分類模型的Logistic回歸模型和Xgboost模型是不用管特征輸入順序的。(這三個是親測,其他的分類模型以后慢慢試)文章來源地址http://www.zghlxwxcb.cn/news/detail-415254.html
八、完整代碼自取
#隨機森林
#導入所需要的包
from sklearn.metrics import precision_score
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import classification_report#評估報告
from sklearn.model_selection import cross_val_score #交叉驗證
from sklearn.model_selection import GridSearchCV #網格搜索
import matplotlib.pyplot as plt#可視化
import seaborn as sns#繪圖包
from sklearn.preprocessing import StandardScaler,MinMaxScaler,MaxAbsScaler#歸一化,標準化
# 忽略警告
import warnings
warnings.filterwarnings("ignore")
datas=pd.read_csv('data_20221030(1).csv')
datas=datas[datas.columns[2:]]
model=RandomForestClassifier(max_depth=8,n_estimators=76,min_samples_leaf=5,min_samples_split=7,max_features='sqrt',criterion='entropy')
# 訓練模型
model.fit(X_train,y_train)
# 預測值
y_pred = model.predict(X_test)
'''
評估指標
'''
# 求出預測和真實一樣的數(shù)目
true = np.sum(y_pred == y_test )
print('預測對的結果數(shù)目為:', true)
print('預測錯的的結果數(shù)目為:', y_test.shape[0]-true)
# 評估指標
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score,cohen_kappa_score
print('預測數(shù)據(jù)的準確率為: {:.4}%'.format(accuracy_score(y_test,y_pred)*100))
print('預測數(shù)據(jù)的精確率為:{:.4}%'.format(
precision_score(y_test,y_pred)*100))
print('預測數(shù)據(jù)的召回率為:{:.4}%'.format(
recall_score(y_test,y_pred)*100))
# print("訓練數(shù)據(jù)的F1值為:", f1score_train)
print('預測數(shù)據(jù)的F1值為:',
f1_score(y_test,y_pred))
print('預測數(shù)據(jù)的Cohen’s Kappa系數(shù)為:',
cohen_kappa_score(y_test,y_pred))
# 打印分類報告
print('預測數(shù)據(jù)的分類報告為:','\n',
classification_report(y_test,y_pred))
到了這里,關于分類算法-隨機森林實戰(zhàn)案例的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!