隨機森林是一種有監督學習算法,是以決策樹爲基學習器的集成學習算法。隨機森林很是簡單,易於實現,計算開銷也很小,可是它在分類和迴歸上表現出很是驚人的性能,所以,隨機森林被譽爲「表明集成學習技術水平的方法」。html
從原始的數據集中採起有放回的抽樣(bagging),構造子數據集,子數據集的數據量是和原始數據集相同的。不一樣子數據集的元素能夠重複,同一個子數據集中的元素也能夠重複。node
與數據集的隨機選取相似,隨機森林中的子樹的每個分裂過程並未用到全部的待選特徵,而是從全部的待選特徵中隨機選取必定的特徵,以後再在隨機選取的特徵中選取最優的特徵python
1,隨機森林既能夠用於分類問題,也能夠用於迴歸問題git
2,過擬合是個關鍵的問題,可能會讓模型的結果變得糟糕,可是對於隨機森林來講,若是隨機森林的樹足夠多,那麼分類器就不會過擬合模型算法
3,隨機森林分類器能夠處理缺失值bootstrap
4,隨機森林分類器能夠用分類值建模api
1,從原始訓練集中使用Bootstraping方法隨機有放回採樣取出m個樣本,共進行n_tree次採樣。生成n_tree個訓練集數組
2,對n_tree個訓練集,咱們分別訓練n_tree個決策樹模型app
3,對於單個決策樹模型,假設訓練樣本特徵的個數爲n,那麼每次分裂時根據信息增益/信息增益比/基尼指數 選擇最好的特徵進行分裂框架
4,每棵樹都已知這樣分裂下去,知道該節點的全部訓練樣例都屬於同一類。在決策樹的分裂過程當中不須要剪枝
5,將生成的多顆決策樹組成隨機森林。對於分類問題,按照多棵樹分類器投票決定最終分類結果;對於迴歸問題,由多顆樹預測值的均值決定最終預測結果
注意:OOB(out-of-bag ):每棵決策樹的生成都須要自助採樣,這時就有1/3的數據未被選中,這部分數據就稱爲袋外數據。
現實狀況下,一個數據集中每每有成百上千個特徵,如何在其中選擇比結果影響最大的那幾個特徵,以此來縮減創建模型時特徵數是咱們比較關心的問題。這樣的方法其實不少,好比主成分分析,lasso等等。不過這裏咱們學習的是用隨機森林來進行特徵篩選。
用隨機森林進行特徵重要性評估的思想就是看每一個特徵在隨機森林中的每棵樹上作了多大的貢獻,而後取個平均值,最後比一比特徵之間的貢獻大小。
貢獻大小一般使用基尼指數(Gini index)或者袋外數據(OOB)錯誤率做爲評估指標來衡量。這裏咱們再學習一下基尼指數來評價的方法。
咱們將變量重要性評分(variable importance measures)用VIM來表示,將Gini指數用GI來表示,假設m個特徵X1,X2,X3,......Xc,如今要計算出每一個特徵Xj的Gini指數評分VIMj(Gini),亦即第j個特徵在RF全部決策樹中節點分裂不純度的平均改變量。
Gini指數的計算公式爲:
其中,K表示有K個類別。Pmk表示節點m中類列k所佔的比例。
直觀的說,就是隨便從節點m中隨機抽取兩個樣本,其類別標記不一致的機率。
特徵Xj在節點m的重要性,即節點m分支先後的Gini指數變化量爲:
其中,GIl和GIr分別表示分枝後兩個新節點的Gini指數。
若是,特徵Xj在決策樹i中出現的節點在集合M中,那麼Xj在第i顆樹的重要性爲:
假設RF中共有n顆樹,那麼
最後,把全部求得的重要性評分作一個歸一化處理便可。
在特徵重要性的基礎上,特徵選擇的步驟以下:
特徵重要性的估計一般有兩種方法:一是使用uniform或者gaussian抽取隨機值替換原特徵;一是經過permutation的方式將原來的全部N個樣本的第i個特徵值從新打亂分佈,第二種方法更加科學,保證了特徵替代值與原特徵的分佈是近似的。這種方法叫作permutation test ,即在計算第i個特徵的重要性的時候,將N 個特徵的第i個特徵從新洗牌,而後比較D和表現的差別性,若是差別很大,則代表第i個特徵是重要的。
代碼:
import numpy as np import pandas as pd from sklearn.ensemble import RandomForestClassifier # url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data' url1 = pd.read_csv(r'wine.txt',header=None) # url1 = pd.DataFrame(url1) # df = pd.read_csv(url1,header=None) url1.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols', 'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue', 'OD280/OD315 of diluted wines', 'Proline'] # print(url1) # 查看幾個標籤 # Class_label = np.unique(url1['Class label']) # print(Class_label) # 查看數據信息 # info_url = url1.info() # print(info_url) # 除去標籤以外,共有13個特徵,數據集的大小爲178, # 下面將數據集分爲訓練集和測試集 from sklearn.model_selection import train_test_split print(type(url1)) # url1 = url1.values # x = url1[:,0] # y = url1[:,1:] x,y = url1.iloc[:,1:].values,url1.iloc[:,0].values x_train,x_test,y_train,y_test = train_test_split(x,y,test_size=0.3,random_state=0) feat_labels = url1.columns[1:] # n_estimators:森林中樹的數量 # n_jobs 整數 可選(默認=1) 適合和預測並行運行的做業數,若是爲-1,則將做業數設置爲核心數 forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=-1) forest.fit(x_train, y_train) # 下面對訓練好的隨機森林,完成重要性評估 # feature_importances_ 能夠調取關於特徵重要程度 importances = forest.feature_importances_ print("重要性:",importances) x_columns = url1.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]])) # 篩選變量(選擇重要性比較高的變量) threshold = 0.15 x_selected = x_train[:,importances > threshold] # 可視化 import matplotlib.pyplot as plt plt.figure(figsize=(10,6)) plt.title("紅酒的數據集中各個特徵的重要程度",fontsize = 18) plt.ylabel("import level",fontsize = 15,rotation=90) plt.rcParams['font.sans-serif'] = ["SimHei"] plt.rcParams['axes.unicode_minus'] = False for i in range(x_columns.shape[0]): plt.bar(i,importances[indices[i]],color='orange',align='center') plt.xticks(np.arange(x_columns.shape[0]),x_columns,rotation=90,fontsize=15) plt.show()
結果:
RangeIndex: 178 entries, 0 to 177 Data columns (total 14 columns): Class label 178 non-null int64 Alcohol 178 non-null float64 Malic acid 178 non-null float64 Ash 178 non-null float64 Alcalinity of ash 178 non-null float64 Magnesium 178 non-null int64 Total phenols 178 non-null float64 Flavanoids 178 non-null float64 Nonflavanoid phenols 178 non-null float64 Proanthocyanins 178 non-null float64 Color intensity 178 non-null float64 Hue 178 non-null float64 OD280/OD315 of diluted wines 178 non-null float64 Proline 178 non-null int64 dtypes: float64(11), int64(3) memory usage: 19.5 KB 重要性: [0.10658906 0.02539968 0.01391619 0.03203319 0.02207807 0.0607176 0.15094795 0.01464516 0.02235112 0.18248262 0.07824279 0.1319868 0.15860977] 1) Color intensity 0.182483 2) Proline 0.158610 3) Flavanoids 0.150948 4) OD280/OD315 of diluted wines 0.131987 5) Alcohol 0.106589 6) Hue 0.078243 7) Total phenols 0.060718 8) Alcalinity of ash 0.032033 9) Malic acid 0.025400 10) Proanthocyanins 0.022351 11) Magnesium 0.022078 12) Nonflavanoid phenols 0.014645 13) Ash 0.013916
圖:
代碼:
from sklearn.svm import SVR # SVM中的迴歸算法 import pandas as pd from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt import numpy as np # 數據預處理,使得數據更加有效的被模型或者評估器識別 from sklearn import preprocessing from sklearn.externals import joblib # 獲取數據 origin_data = pd.read_csv('wine.txt',header=None) X = origin_data.iloc[:,1:].values Y = origin_data.iloc[:,0].values print(type(Y)) # print(type(Y.values)) # 總特徵 按照特徵的重要性排序的全部特徵 all_feature = [ 9, 12, 6, 11, 0, 10, 5, 3, 1, 8, 4, 7, 2] # 這裏咱們選取前三個特徵 topN_feature = all_feature[:3] print(topN_feature) # 獲取重要特徵的數據 data_X = X[:,topN_feature] # 將每一個特徵值歸一化到一個固定範圍 # 原始數據標準化,爲了加速收斂 # 最小最大規範化對原始數據進行線性變換,變換到[0,1]區間 data_X = preprocessing.MinMaxScaler().fit_transform(data_X) # 利用train_test_split 進行訓練集和測試集進行分開 X_train,X_test,y_train,y_test = train_test_split(data_X,Y,test_size=0.3) # 經過多種模型預測 model_svr1 = SVR(kernel='rbf',C=50,max_iter=10000) # 訓練 # model_svr1.fit(data_X,Y) model_svr1.fit(X_train,y_train) # 得分 score = model_svr1.score(X_test,y_test) print(score)
結果:
0.8211850237886935
sklearn.ensemble模塊包含了兩種基於隨機決策樹的平均算法:RandomForest算法和Extra-Trees算法。這兩種算法都採用了很流行的樹設計思想:perturb-and-combine思想。這種方法會在分類器的構建時,經過引入隨機化,建立一組各不同(diverse)的分類器。這種ensemble方法的預測會給出各個分類器預測的平均。
在sklearn.ensemble庫中,咱們能夠找到Random Forest分類和迴歸的實現:RandomForestClassifier和RandomForestRegression 有了這些模型後,咱們的作法是立立刻手操做,由於學習中提供的示例都很簡單,可是實際中遇到不少問題,下面概述一下:
在scikit-learn中,RF的分類類是RandomForestClassifier,迴歸類是RandomForestRegressor。固然RF的變種Extra Trees也有,分類類ExtraTreesClassifier,迴歸類ExtraTreesRegressor。因爲RF和Extra Trees的區別較小,調參方法基本相同,本文只關注於RF的調參。
在隨機森林(RF)中,該ensemble方法中的每棵樹都基於一個經過可放回抽樣(boostrap)獲得的訓練集構建。另外,在構建樹的過程當中,當split一個節點時,split的選擇再也不是對全部features的最佳選擇。相反的,在features的子集中隨機進行split反卻是最好的split方式。這種隨機的後果是,整個forest的bias,從而獲得一個更好的模型。
sklearn的隨機森林(RF)實現經過對各分類結果預測求平均獲得,而非讓每一個分類器進行投票(vote)。
在Ext-Trees中(詳見ExtraTreesClassifier和 ExtraTreesRegressor),該方法中,隨機性在劃分時會更進一步進行計算。在隨機森林中,會使用侯選feature的一個隨機子集,而非查找最好的閾值,對於每一個候選feature來講,閾值是抽取的,選擇這種隨機生成閾值的方式做爲劃分原則。一般狀況下,在減少模型的variance的同時,適當增長bias是容許的。
首先看一個類的參數:
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=’auto’, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=1, random_state=None, verbose=0, warm_start=False, class_weight=None)
和GBDT對比,GBDT的框架參數比較多,重要的有最大迭代器個數,步長和子採樣比例,調參起來比較費力。可是RF則比較簡單,這是由於Bagging框架裏的各個弱學習器之間是沒有依賴關係的,這減少調參的難度,換句話說,達到一樣的調參效果,RF調參數時間要比GBDT少一些,
下面我來看看RF重要的Bagging框架的參數,因爲RandomForestClassifier和RandomForestRegressor參數絕大部分相同,這裏會將它們一塊兒講,不一樣點會指出。
1) n_estimators: 也就是弱學習器的最大迭代次數,或者說最大的弱學習器的個數。通常來講n_estimators過小,容易欠擬合,n_estimators太大,又容易過擬合,通常選擇一個適中的數值。RandomForestClassifier和RandomForestRegressor默認是10。在實際調參的過程當中,咱們經常將n_estimators和下面介紹的參數learning_rate一塊兒考慮。
2) oob_score :便是否採用袋外樣原本評估模型的好壞。默認識False。有放回採樣中大約36.8%的沒有被採樣到的數據,咱們經常稱之爲袋外數據(Out Of Bag 簡稱OOB),這些數據沒有參與訓練集模型的擬合,所以能夠用來檢測模型的泛化能力。我的推薦設置爲True,由於袋外分數反應了一個模型擬合後的泛化能力。
3) criterion: 即CART樹作劃分時對特徵的評價標準。分類模型和迴歸模型的損失函數是不同的。分類RF對應的CART分類樹默認是基尼係數gini,另外一個可選擇的標準是信息增益。迴歸RF對應的CART迴歸樹默認是均方差mse,另外一個能夠選擇的標準是絕對值差mae。通常來講選擇默認的標準就已經很好的。
4)bootstrap:默認是True,是否有放回的採樣。
5)verbose:日誌亢長度,int表示亢長度,o表示輸出訓練過程,1表示偶爾輸出 ,>1表示對每一個子模型都輸出
從上面能夠看出, RF重要的框架參數比較少,主要須要關注的是 n_estimators,即RF最大的決策樹個數。當使用這些方法的時候,最主要的參數是調整n_estimators和max_features。n_estimators指的是森林中樹的個數,樹數目越大越好,可是會增長計算開銷,另外,注意若是超過限定數量後,計算將會中止。
下面咱們再來看RF的決策樹參數,它要調參的參數基本和GBDT相同,以下:
1) RF劃分時考慮的最大特徵數max_features: 可使用不少種類型的值,默認是"None",意味着劃分時考慮全部的特徵數;若是是"log2"意味着劃分時最多考慮個特徵;若是是"sqrt"或者"auto"意味着劃分時最多考慮個特徵。若是是整數,表明考慮的特徵絕對數。若是是浮點數,表明考慮特徵百分比,即考慮(百分比xN)取整後的特徵數。其中N爲樣本總特徵數。通常來講,若是樣本特徵數很少,好比小於50,咱們用默認的"None"就能夠了,若是特徵數很是多,咱們能夠靈活使用剛纔描述的其餘取值來控制劃分時考慮的最大特徵數,以控制決策樹的生成時間。max_features指的是,當劃分一個節點的時候,features的隨機子集的size,該值越小,variance會變小,可是bais會變大。(int 表示個數,float表示佔全部特徵的百分比,auto表示全部特徵數的開方,sqrt表示全部特徵數的開放,log2表示全部特徵數的log2值,None表示等於全部特徵數)
2) 決策樹最大深度max_depth: 默承認以不輸入,若是不輸入的話,決策樹在創建子樹的時候不會限制子樹的深度。通常來講,數據少或者特徵少的時候能夠無論這個值。若是模型樣本量多,特徵也多的狀況下,推薦限制這個最大深度,具體的取值取決於數據的分佈。經常使用的能夠取值10-100之間。(int表示深度,None表示樹會生長到全部葉子都分到一個類,或者某節點所表明的樣本已小於min_samples_split)
3) 內部節點再劃分所需最小樣本數min_samples_split: 這個值限制了子樹繼續劃分的條件,若是某節點的樣本數少於min_samples_split,則不會繼續再嘗試選擇最優特徵來進行劃分。 默認是2.若是樣本量不大,不須要管這個值。若是樣本量數量級很是大,則推薦增大這個值。(int表示樣本數,2表示默認值)
4) 葉子節點最少樣本數min_samples_leaf: 這個值限制了葉子節點最少的樣本數,若是某葉子節點數目小於樣本數,則會和兄弟節點一塊兒被剪枝。 默認是1,能夠輸入最少的樣本數的整數,或者最少樣本數佔樣本總數的百分比。若是樣本量不大,不須要管這個值。若是樣本量數量級很是大,則推薦增大這個值。
5)葉子節點最小的樣本權重和min_weight_fraction_leaf:這個值限制了葉子節點全部樣本權重和的最小值,若是小於這個值,則會和兄弟節點一塊兒被剪枝。 默認是0,就是不考慮權重問題。通常來講,若是咱們有較多樣本有缺失值,或者分類樹樣本的分佈類別誤差很大,就會引入樣本權重,這時咱們就要注意這個值了。
6) 最大葉子節點數max_leaf_nodes: 經過限制最大葉子節點數,能夠防止過擬合,默認是"None」,即不限制最大的葉子節點數。若是加了限制,算法會創建在最大葉子節點數內最優的決策樹。若是特徵很少,能夠不考慮這個值,可是若是特徵分紅多的話,能夠加以限制,具體的值能夠經過交叉驗證獲得。
7) 節點劃分最小不純度min_impurity_split: 這個值限制了決策樹的增加,若是某節點的不純度(基於基尼係數,均方差)小於這個閾值,則該節點再也不生成子節點。即爲葉子節點 。通常不推薦改動默認值1e-7。
8)用於擬合和預測的並行運行的工做數量n_jobs:通常取整數,可選的(默認值爲1),若是爲-1,那麼工做數量被設置爲核的數量,機器上全部的核都會被使用(跟CPU核數一致)。若是n_jobs=k,則計算被劃分爲k個job,並運行在K核上。注意,因爲進程間通訊的開銷,加速效果並不會是線性的(job數K不會提示K倍)經過構建大量的樹,比起單顆樹所須要的時間,性能也能獲得很大的提高,
9)隨機數生成器random_state:隨機數生成器使用的種子,若是是RandomState實例,則random_stats就是隨機數生成器;若是爲None,則隨機數生成器是np.random使用的RandomState實例。
上面決策樹參數中最重要的包括最大特徵數max_features, 最大深度max_depth, 內部節點再劃分所需最小樣本數min_samples_split和葉子節點最少樣本數min_samples_leaf。
根據經驗
對於迴歸問題:好的缺省值max_features = n_features;
對於分類問題:好的缺省值是max_features=sqrt(n_features)。n_features指的是數據中的feature總數。
當設置max_depth=None,以及min_samples_split=1時,一般會獲得好的結果(徹底展開的樹)。但須要注意,這些值一般不是最優的,而且會浪費RAM內存。最好的參數應經過cross-validation給出。另外須要注意:
在隨機森林中,缺省時會使用bootstrap進行樣本抽樣(bootstrap=True) ;
而extra-trees中,缺省策略爲不使用bootstrap抽樣 (bootstrap=False);
當使用bootstrap樣本時,泛化偏差可能在估計時落在out-of-bag樣本中。此時,能夠經過設置oob_score=True來開啓。
參數分類的目的在於縮小調參的範圍,首先咱們要明確訓練的目標,把目標類的參數定下來。接下來,咱們須要根據數據集的大小,考慮是否採用一些提升訓練效率的策略,不然一次訓練就三天三夜,時間過久了,因此咱們須要調整哪些影響總體的模型性能的參數。
誤差和方差經過準確率來影響着模型的性能。調參的目標就是爲了達到總體模型的誤差和方差的大和諧!進一步,這些參數又能夠分爲兩類:過程影響類及子模型影響類。在子模型不變的前提下,某些參數能夠經過改變訓練的過程,從而影響着模型的性能,諸如:「子模型數」(n_estimators),「學習率」(learning_rate)等,另外,咱們還能夠經過改變子模型性能來影響總體模型的性能,諸如:「最大樹深度」(max_depth),‘分裂條件’(criterion)等。正因爲bagging的訓練過程旨在下降方差,而Boosting的訓練過程旨在下降誤差,過程影響類的參數可以引發總體模型性能的大幅度變化。通常來講,在此前提下,咱們繼續微調子模型影響類的參數,從而進一步提升模型的性能。
假設模型是一個多元函數F,其輸出值爲模型的準確度。咱們能夠固定其餘參數,從而對某個參數總體模型性能的影響進行分析:是正影響仍是負影響,影響的單調性?
對Random Forest來講,增長「子模型樹」(n_estimators)能夠明顯下降總體模型的方差,且不會對子模型的誤差和方差有任何影響。模型的準確度會隨着「子模型數」的增長而提升,因爲減小的是總體模型方差公式的第二項,故準確度的提升有一個上線。在不一樣的場景下,「分裂條件」(criterion)對模型的準確度的影響也不同,該參數須要在實際運行時靈活調整。調整「最大葉子節點數」(max_leaf_models)以及「最大樹深度」(max_depth)之一,能夠粗粒度地調整樹的結構:葉節點越多或者樹越深,意味着子模型的誤差月底,方差越高;同時,調整」分裂所須要最小樣本數」(min_samples_split),「葉節點最小樣本數」(min_samples_leaf)及「葉節點最小權重總值」(min_weight_fraction_leaf),能夠更細粒度地調整樹的結構:分裂所需樣本數越少或者葉節點所需樣本越少,也意味着子模型越複雜。通常來講,咱們總採用bootstrap對樣本進行子採樣來下降子模型之間的關聯度,從而下降總體模型的方差。適當地減小「分裂時考慮的最大特徵數」(max_features),給子模型注入了另外的隨機性,一樣也達到了下降子模型之間關聯度的效果。可是一味地下降該參數也是不行的,由於分裂時可選特徵變少,模型的誤差會愈來愈大。在下圖中,咱們能夠看到這些參數對Random Forest總體模型性能的影響:
到此爲止,咱們終於知道須要調整哪些參數,對於單個參數,咱們也知道怎麼調整才能提高性能。而後,表示模型的函數F並非一元函數,這些參數須要共同調參才能獲得全局最優解。也就是說,把這些參數丟給調參算法(諸如Grid Search)?對於小數據集,咱們還能這麼任性,可是參數組合爆炸,在大數據集上,實際上網格搜索也不必定能獲得全局最優解。
座標降低法是一類優化算法,其最大的優點在於不一樣計算待優化的目標函數的梯度。咱們最容易想到一種特別樸實的相似於座標降低法的方法,與座標降低法不一樣的是,其不一樣循環使用各個參數進行調整,而是貪心地選取了對總體模型性能影響最大的參數。參數對總體模型性能的影響力是動態變化的,故每一輪座標選取的過程當中,這種方法在對每一個座標的降低方向進行一次直線搜索(line search)。首先,找到那些可以提高總體模型性能的參數,其次確保提高是單調或者近似單調。這意味着,咱們篩選出來的參數是總體模型性能有正影響的,且這種影響不是偶然性的,要知道,訓練過程的隨機性也會致使總體模型性能的細微區別,而這種區別是不具備單調性的。最後,在這些篩選出來的參數中,選取影響最大的參數進行調整便可。
沒法對總體模型性能進行量化,也就談不上去比較參數影響總體模型性能的程度,是的,咱們尚未一個準確的方法來量化總體模型性能,只能經過交叉驗證來近似計算總體模型性能。然而交叉驗證也存在隨機性,假設咱們以驗證集上的平均準確度做爲總體模型的準確度,咱們還得關心在各個驗證集上準確度的變異係數,若是變異係數過大,則平均值做爲總體模型的準確率也是不合適的。在接下來的案例分析中,咱們所談及的總體模型性能均是指平均準確度。
若是想看完整數據及其代碼:請點擊我
def random_forest_parameter_tuning1(feature_data, label_data, test_feature): from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn.model_selection import GridSearchCV X_train, X_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.23) param_test1 = { 'n_estimators': range(10, 71, 10) } model = GridSearchCV(estimator=RandomForestRegressor( min_samples_split=100, min_samples_leaf=20, max_depth=8, max_features='sqrt', random_state=10), param_grid=param_test1, cv=5 ) model.fit(X_train, y_train) # 對測試集進行預測 y_pred = model.predict(X_test) # 計算準確率 MSE = mean_squared_error(y_test, y_pred) RMSE = np.sqrt(MSE) print(RMSE) return model.best_score_, model.best_params_
結果以下:
{'n_estimators': 70} 0.6573670183811001
這樣咱們獲得了最佳的弱學習器迭代次數,爲70.。
咱們首先獲得了最佳弱學習器迭代次數,接着咱們對決策樹最大深度max_depth和內部節點再劃分所須要最小樣本數min_samples_split進行網格搜索。
def random_forest_parameter_tuning2(feature_data, label_data, test_feature): from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn.model_selection import GridSearchCV X_train, X_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.23) param_test2 = { 'max_depth': range(3, 14, 2), 'min_samples_split': range(50, 201, 20) } model = GridSearchCV(estimator=RandomForestRegressor( n_estimators=70, min_samples_leaf=20, max_features='sqrt', oob_score=True, random_state=10), param_grid=param_test2, cv=5 ) model.fit(X_train, y_train) # 對測試集進行預測 y_pred = model.predict(X_test) # 計算準確率 MSE = mean_squared_error(y_test, y_pred) RMSE = np.sqrt(MSE) print(RMSE) return model.best_score_, model.best_params_
結果爲:
{'max_depth': 13, 'min_samples_split': 50} 0.7107311632187736
對於內部節點再劃分所須要最小樣本數min_samples_split,咱們暫時不能一塊兒定下來,由於這個還和決策樹其餘的參數存在關聯。
下面咱們對內部節點在劃分所須要最小樣本數min_samples_split和葉子節點最小樣本數min_samples_leaf一塊兒調參。
def random_forest_parameter_tuning3(feature_data, label_data, test_feature): from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn.model_selection import GridSearchCV X_train, X_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.23) param_test3 = { 'min_samples_split': range(10, 90, 20), 'min_samples_leaf': range(10, 60, 10), } model = GridSearchCV(estimator=RandomForestRegressor( n_estimators=70, max_depth=13, max_features='sqrt', oob_score=True, random_state=10), param_grid=param_test3, cv=5 ) model.fit(X_train, y_train) # 對測試集進行預測 y_pred = model.predict(X_test) # 計算準確率 MSE = mean_squared_error(y_test, y_pred) RMSE = np.sqrt(MSE) print(RMSE) return model.best_score_, model.best_params_
結果以下:
{'min_samples_leaf': 10, 'min_samples_split': 10} 0.7648492269870218
def random_forest_parameter_tuning4(feature_data, label_data, test_feature): from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error from sklearn.model_selection import GridSearchCV X_train, X_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.23) param_test3 = { 'max_features': range(3, 9, 2), } model = GridSearchCV(estimator=RandomForestRegressor( n_estimators=70, max_depth=13, min_samples_split=10, min_samples_leaf=10, oob_score=True, random_state=10), param_grid=param_test3, cv=5 ) model.fit(X_train, y_train) # 對測試集進行預測 y_pred = model.predict(X_test) # 計算準確率 MSE = mean_squared_error(y_test, y_pred) RMSE = np.sqrt(MSE) print(RMSE) return model.best_score_, model.best_params_
結果以下:
{'max_features': 7} 0.881211719251515
def random_forest_train(feature_data, label_data, test_feature, submitfile): from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error X_train, X_test, y_train, y_test = train_test_split(feature_data, label_data, test_size=0.23) params = { 'n_estimators': 70, 'max_depth': 13, 'min_samples_split': 10, 'min_samples_leaf': 10, 'max_features': 7 } model = RandomForestRegressor(**params) model.fit(X_train, y_train) # 對測試集進行預測 y_pred = model.predict(X_test) # 計算準確率 MSE = mean_squared_error(y_test, y_pred) RMSE = np.sqrt(MSE) print(RMSE) submit = pd.read_csv(submitfile) submit['y'] = model.predict(test_feature) submit.to_csv('my_random_forest_prediction1.csv', index=False)
在這裏,咱們選取Kaggle上101教學賽的Digit Recognizer做爲案例來演示對RandomForestClassifier調參的過程。固然,咱們也不要傻乎乎地手工去設定不一樣的參數,而後訓練模型,藉助sklearn.grid_search庫中的GridSearchCV類,不只能夠自動化調參,同時還能夠對每一種參數組合進行交叉驗證計算平均準確度。
>>> from sklearn.ensemble import RandomForestClassifier >>> from sklearn.datasets import make_classification >>> >>> X, y = make_classification(n_samples=1000, n_features=4, ... n_informative=2, n_redundant=0, ... random_state=0, shuffle=False) >>> clf = RandomForestClassifier(max_depth=2, random_state=0) >>> clf.fit(X, y) RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=2, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1, oob_score=False, random_state=0, verbose=0, warm_start=False) >>> print(clf.feature_importances_) [ 0.17287856 0.80608704 0.01884792 0.00218648] >>> print(clf.predict([[0, 0, 0, 0]])) [1]
1 ) predict_proba(x) : 給出帶有機率值的結果。每一個點在全部label(類別)的機率和爲1.
2) predict(x): 直接給出預測結果,內部仍是調用的predict_proba()。根據機率的結果看哪一個類型的預測值最高就是那個類型。
3)predict_log_proba(x): 和predict_proba基本上同樣,只是把結果作了log()處理。
>>> from sklearn.cross_validation import cross_val_score >>> from sklearn.datasets import make_blobs >>> from sklearn.ensemble import RandomForestClassifier >>> from sklearn.ensemble import ExtraTreesClassifier >>> from sklearn.tree import DecisionTreeClassifier >>> X, y = make_blobs(n_samples=10000, n_features=10, centers=100, ... random_state=0) >>> clf = DecisionTreeClassifier(max_depth=None, min_samples_split=1, ... random_state=0) >>> scores = cross_val_score(clf, X, y) >>> scores.mean() 0.97... >>> clf = RandomForestClassifier(n_estimators=10, max_depth=None, ... min_samples_split=1, random_state=0) >>> scores = cross_val_score(clf, X, y) >>> scores.mean() 0.999... >>> clf = ExtraTreesClassifier(n_estimators=10, max_depth=None, ... min_samples_split=1, random_state=0) >>> scores = cross_val_score(clf, X, y) >>> scores.mean() > 0.999 True
代碼:
#_*_coding:UTF_8_*_ # 導入須要導入的庫 import pandas as pd import numpy as np import math from sklearn.ensemble import RandomForestClassifier from sklearn.ensemble import ExtraTreesClassifier from sklearn.tree import DecisionTreeClassifier from sklearn import model_selection ,metrics from sklearn.model_selection import cross_val_score from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt import matplotlib as mpl from sklearn.datasets import make_blobs import warnings # 忽略一些版本不兼容等警告 warnings.filterwarnings("ignore") # 每一個樣本有幾個屬性或者特徵 n_features = 2 x,y = make_blobs(n_samples=300,n_features=n_features,centers=6) x_train,x_test,y_train,y_test = train_test_split(x,y,random_state=1,train_size=0.7) # 繪製樣本顯示 # plt.scatter(x[:,0],x[:,1],c=y) # plt.show() # 傳統決策樹,隨機森林算法 極端隨機數的區別 DT = DecisionTreeClassifier(max_depth=None,min_samples_split=2,random_state=0) RF = RandomForestClassifier(n_estimators=10,max_features=math.sqrt(n_features), max_depth=None,min_samples_split=2,bootstrap=True) EC = ExtraTreesClassifier(n_estimators=10,max_features=math.sqrt(n_features), max_depth=None,min_samples_split=2,bootstrap=False) # 訓練 DT.fit(x_train,y_train) RF.fit(x_train,y_train) EC.fit(x_train,y_train) #區域預測 # 第0列的範圍 x1_min,x1_max = x[:,0].min(),x[:,0].max() # 第1列的範圍 x2_min,x2_max = x[:,1].min(),x[:,1].max() # 生成網格採樣點行列均爲200點 x1,x2 = np.mgrid[x1_min:x1_max:200j,x2_min:x2_max:200j] # 將區域劃分爲一系列測試點用去學習的模型預測,進而根據預測結果畫區域 area_sample_point = np.stack((x1.flat,x2.flat),axis=1) # 全部區域點進行預測 area1_predict = DT.predict(area_sample_point) area1_predict = area1_predict.reshape(x1.shape) area2_predict = RF.predict(area_sample_point) area2_predict = area2_predict.reshape(x1.shape) area3_predict = EC.predict(area_sample_point) area3_predict = area3_predict.reshape(x1.shape) # 用來正常顯示中文標籤 mpl.rcParams['font.sans-serif'] = [u'SimHei'] # 用來正常顯示負號 mpl.rcParams['axes.unicode_minus'] = False # 區域顏色 classifier_area_color = mpl.colors.ListedColormap(['#A0FFA0','#FFA0A0','#A0A0FF']) # 樣本所屬類別顏色 cm_dark = mpl.colors.ListedColormap(['r','g','b']) # 繪圖 # 第一個子圖 plt.subplot(2,2,1) plt.pcolormesh(x1,x2,area1_predict,cmap = classifier_area_color) plt.scatter(x_train[:,0],x_train[:,1],c =y_train,marker='o',s=50,cmap=cm_dark) plt.scatter(x_test[:,0],x_test[:,1],c =y_test,marker='x',s=50,cmap=cm_dark) plt.xlabel('data_x',fontsize=8) plt.ylabel('data_y',fontsize=8) plt.xlim(x1_min,x1_max) plt.ylim(x2_min,x2_max) plt.title(u'DecisionTreeClassifier: 傳統決策樹',fontsize=8) plt.text(x1_max-9,x2_max-2,u'o-------train ; x--------test$') # 第二個子圖 plt.subplot(2,2,2) plt.pcolormesh(x1,x2,area2_predict,cmap = classifier_area_color) plt.scatter(x_train[:,0],x_train[:,1],c =y_train,marker='o',s=50,cmap=cm_dark) plt.scatter(x_test[:,0],x_test[:,1],c =y_test,marker='x',s=50,cmap=cm_dark) plt.xlabel('data_x',fontsize=8) plt.ylabel('data_y',fontsize=8) plt.xlim(x1_min,x1_max) plt.ylim(x2_min,x2_max) plt.title(u'RandomForestClassifier: 隨機森林算法',fontsize=8) plt.text(x1_max-9,x2_max-2,u'o-------train ; x--------test$') # 第三個子圖 plt.subplot(2,2,3) plt.pcolormesh(x1,x2,area3_predict,cmap = classifier_area_color) plt.scatter(x_train[:,0],x_train[:,1],c =y_train,marker='o',s=50,cmap=cm_dark) plt.scatter(x_test[:,0],x_test[:,1],c =y_test,marker='x',s=50,cmap=cm_dark) plt.xlabel('data_x',fontsize=8) plt.ylabel('data_y',fontsize=8) plt.xlim(x1_min,x1_max) plt.ylim(x2_min,x2_max) plt.title(u'ExtraTreesClassifier: 極端隨機樹',fontsize=8) plt.text(x1_max-9,x2_max-2,u'o-------train ; x--------test$') # 第四個子圖 plt.subplot(2,2,4) y = [] # 交叉驗證 score_DT = cross_val_score(DT,x_train,y_train) y.append(score_DT.mean()) score_RF = cross_val_score(RF,x_train,y_train) y.append(score_RF.mean()) score_EC = cross_val_score(EC,x_train,y_train) y.append(score_EC.mean()) print('DecisionTreeClassifier交叉驗證準確率爲:'+str(score_DT.mean())) print('RandomForestClassifier交叉驗證準確率爲:'+str(score_RF.mean())) print('ExtraTreesClassifier交叉驗證準確率爲:'+str(score_EC.mean())) x = [0,1,2] plt.bar(x,y,0.4,color='green') plt.xlabel("0--DecisionTreeClassifier;1--RandomForestClassifier;2--ExtraTreesClassifie", fontsize=8) plt.ylabel("平均準確率", fontsize=8) plt.ylim(0.9, 0.99) plt.title("交叉驗證", fontsize=8) for a, b in zip(x, y): plt.text(a, b, b, ha='center', va='bottom', fontsize=10) plt.show()
結果:
代碼:
#隨機森林迴歸 import matplotlib as mpl import numpy as np import warnings import matplotlib.pyplot as plt from sklearn.tree import DecisionTreeRegressor from sklearn.ensemble import RandomForestRegressor from sklearn.ensemble import ExtraTreesRegressor #忽略一些版本不兼容等警告 warnings.filterwarnings("ignore") #產生心狀座標 t = np.arange(0,2*np.pi,0.1) x = 16*np.sin(t)**3 x=x[:, np.newaxis] y = 13*np.cos(t)-5*np.cos(2*t)-2*np.cos(3*t)-np.cos(4*t) y[::7]+= 3* (1 - np.random.rand(9)) #增長噪聲,在每數2個數的時候增長一點噪聲 #傳統決策樹線性迴歸,隨機森林迴歸,極端森林迴歸 rf1=DecisionTreeRegressor() rf2=RandomForestRegressor(n_estimators=1000) #通常來講n_estimators越大越好,運行結果呈現出的兩種結果該值分別是10和1000 rf3=ExtraTreesRegressor() #三種算法的預測 y_rf1 =rf1.fit(x,y).predict(x) y_rf2 =rf2.fit(x,y).predict(x) y_rf3 =rf3.fit(x,y).predict(x) #爲了後面plt.text定位 x1_min, x1_max = x[:].min(), x[:].max() x2_min, x2_max = y[:].min(), y[:].max() mpl.rcParams['font.sans-serif'] = [u'SimHei'] #用來正常顯示中文標籤 mpl.rcParams['axes.unicode_minus'] = False plt.scatter(x, y, color='darkorange', label='data') plt.hold('on') plt.plot(x, y_rf1, color='b', label='DecisionTreeRegressor') plt.plot(x, y_rf2, color='g', label='RandomForestRegressor') plt.plot(x, y_rf3, color='r', label='ExtraTreesRegressor') plt.xlabel('data_x') plt.ylabel('data_y') plt.title('python_machine-learning_RandomForest(n_estimators=1000)-----心狀學習') plt.legend() plt.text(x1_max-4, x2_max-1, u'$o---Sample-Point$') plt.show()
結果:
代碼:
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn.cross_validation import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.datasets import make_moons, make_circles, make_classification from sklearn.neighbors import KNeighborsClassifier from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier from sklearn.naive_bayes import GaussianNB from sklearn.lda import LDA from sklearn.qda import QDA h = .02 # step size in the mesh names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Decision Tree", "Random Forest", "AdaBoost", "Naive Bayes", "LDA", "QDA"] classifiers = [ KNeighborsClassifier(3), SVC(kernel="linear", C=0.025), SVC(gamma=2, C=1), DecisionTreeClassifier(max_depth=5), RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1), AdaBoostClassifier(), GaussianNB(), LDA(), QDA()] X, y = make_classification(n_features=2, n_redundant=0, n_informative=2, random_state=1, n_clusters_per_class=1) rng = np.random.RandomState(2) X += 2 * rng.uniform(size=X.shape) linearly_separable = (X, y) datasets = [make_moons(noise=0.3, random_state=0), make_circles(noise=0.2, factor=0.5, random_state=1), linearly_separable ] figure = plt.figure(figsize=(27, 9)) i = 1 # iterate over datasets for ds in datasets: # preprocess dataset, split into training and test part X, y = ds X = StandardScaler().fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4) x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5 xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) # just plot the dataset first cm = plt.cm.RdBu cm_bright = ListedColormap(['#FF0000', '#0000FF']) ax = plt.subplot(len(datasets), len(classifiers) + 1, i) # Plot the training points ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright) # and testing points ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6) ax.set_xlim(xx.min(), xx.max()) ax.set_ylim(yy.min(), yy.max()) ax.set_xticks(()) ax.set_yticks(()) i += 1 # iterate over classifiers for name, clf in zip(names, classifiers): ax = plt.subplot(len(datasets), len(classifiers) + 1, i) clf.fit(X_train, y_train) score = clf.score(X_test, y_test) # Plot the decision boundary. For that, we will assign a color to each # point in the mesh [x_min, m_max]x[y_min, y_max]. if hasattr(clf, "decision_function"): Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) else: Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1] # Put the result into a color plot Z = Z.reshape(xx.shape) ax.contourf(xx, yy, Z, cmap=cm, alpha=.8) # Plot also the training points ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright) # and testing points ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6) ax.set_xlim(xx.min(), xx.max()) ax.set_ylim(yy.min(), yy.max()) ax.set_xticks(()) ax.set_yticks(()) ax.set_title(name) ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'), size=15, horizontalalignment='right') i += 1 figure.subplots_adjust(left=.02, right=.98) plt.show()
結果:
這裏隨機生成了三個樣本集,分割面近似爲月形、圓形和線形的。咱們能夠重點對比一下決策樹和隨機森林對樣本空間的分割:
1)從準確率上能夠看出,隨機森林在這三個測試集上都要優於單棵決策樹,90%>85%,82%>80%,95%=95%;
2)從特徵空間上直觀地能夠看出,隨機森林比決策樹擁有更強的分割能力(非線性擬合能力)。
在sklearn模型訓練出現以下錯誤:
‘ValueError: Unknown label type: ‘unknown’
解決方法:以GBDT爲例:train_y後加上astype(‘int’)便可
gbdt.fit(train_x,train_y.astype(‘int’))
集成學習:https://scikit-learn.org/dev/modules/ensemble.html
https://www.jianshu.com/p/a779f0686acc
https://blog.csdn.net/qq547276542/article/details/78304454
https://blog.csdn.net/sun_shengyun/article/details/54618121
https://blog.csdn.net/zjuPeco/article/details/77371645?locationNum=7&fps=1
https://www.cnblogs.com/simpleDi/p/9979818.html