kaggle數據挖掘競賽初步--Titanic<隨機森林&特征重要性>


完整代碼: https://github.com/cindycindyhi/kaggle-Titanic

特征工程系列:

Titanic系列之原始數據分析和數據處理

Titanic系列之數據變換

Titanic系列之派生屬性&維歸約

之前的三篇博文已經進行了一次還算完整的特征工程,分析字符串類型的變量獲取新變量,對數值變量進行規范化,獲取派生屬性並進行維規約。現在我們已經有了一個特征集,可以進行訓練模型了。

由於這是一個分類問題,可以使用L1 SVM 隨機森林等分類算法,隨機森林是一個非常簡單而且實用的分類模型,可調的變量很少。它的一個非常重要的變量是樹的個數,樹的個數增加到一定大小后會使耗時加大,但是精度不會增加很多。

經過之前的特征工程,現在已經有237個特征,數目過多的特征會使模型過擬合,幸運的是,隨機森林在訓練之后可以產生一個各個特征重要性的數據集,我們可以利用這個數據集,確定一個閾值,選出來對模型訓練幫助最大的一些屬性,這里使用的隨機森林的參數都是默認值。

 1     X = input_df.values[:, 1::]
 2     y = input_df.values[:, 0]
 3     survived_weight = .75
 4     y_weights = np.array([survived_weight if s == 0 else 1 for s in y])
 5 
 6     print "Rough fitting a RandomForest to determine feature importance..."
 7     forest = RandomForestClassifier(oob_score=True, n_estimators=10000)
 8     forest.fit(X, y, sample_weight=y_weights)
 9     feature_importance = forest.feature_importances_
10     feature_importance = 100.0 * (feature_importance / feature_importance.max())
11 
12     fi_threshold = 18    
13     important_idx = np.where(feature_importance > fi_threshold)[0]
14     important_features = features_list[important_idx]
15     print "\n", important_features.shape[0], "Important features(>", \
16           fi_threshold, "% of max importance)...\n"#, \
17             #important_features
18     sorted_idx = np.argsort(feature_importance[important_idx])[::-1]
19     #get the figure about important features
20     pos = np.arange(sorted_idx.shape[0]) + .5
21     plt.subplot(1, 2, 2)
22     plt.title('Feature Importance')
23     plt.barh(pos, feature_importance[important_idx][sorted_idx[::-1]], \
24             color='r',align='center')
25     plt.yticks(pos, important_features[sorted_idx[::-1]])
26     plt.xlabel('Relative Importance')
27     plt.draw()
28     plt.show()

代碼有點長,但主要分成兩塊,一是模型訓練,二是根據訓練得到的特征重要性篩選重要特征並畫圖。

得到的特征重要性大於18的屬性如下圖所示:

可以看到Tiltle_Mr Title_id Gender這三個屬性相當重要。而與Title有關的屬性都是我們對姓名進行分析得到的,可見一些字符串屬性中可能會藏有非常重要的信息,在特種工程中要非常重視而不是將其拋棄。因為我們的原始屬性非常少,所以產生的重要屬性大都是原始屬性的數學組合,派生變量可能並不是必需的,這主要和模型有關,但大多數時候派生變量是沒有什么壞處的。對於隨機森林這種訓練數據想對容易的模型來說,可能一些原始的屬性直接用來進行訓練也會產生很好的效果,但是作為一道學習題,當然是什么處理辦法都要嘗試一遍,積累經驗啦。

對於隨機森林如何得到變臉重要性的,可以看一下scikit learn 的官方文檔 scikit-learn.org/stable/auto_examples/ensemble/plot_forest_importances.html#example-ensemble-plot-forest-importances-py

當然在得到重要的特征后,我們就要把不重要的特征去掉了,以提高模型的訓練速度(閾值可調的小一點,以保留更多的特征)

1     X = X[:, important_idx][:, sorted_idx]
2     submit_df = submit_df.iloc[:,important_idx].iloc[:,sorted_idx]

現在我們就得到了最終的數據集,終於可以正式用來訓練模型了。

上面部分都是用的隨機森林的默認參數,但是模型的參數是可調的,我們要調整參數以獲得更好的訓練。scikit learn 提供了兩種參數優化的方法,也是其他工具通用的方法,一是GridSearch,另一個是RandomizedSearch。這兩種情況下,都可以指定每個參數取值范圍,創建一個字典。將參數字典提供給search方法,它就會執行模型所指定的值的組合對於GridSearch它測試參數每一個可能的組合 RandomizedSearch允許指定有多少不同的組合要測試,然后隨機選擇組合如果正在使用模型關鍵參數很多,RandomizedSearch很有用可以幫助節省時間

 1 sqrtfeat = int(np.sqrt(X.shape[1]))
 2 minsampsplit = int(X.shape[0]*0.015)
 3 # (adapted from http://scikit-learn.org/stable/auto_examples/randomized_search.html)
 4 def report(grid_scores, n_top=5):
 5     params = None
 6     top_scores = sorted(grid_scores, key=itemgetter(1), reverse=True)[:n_top]
 7     for i, score in enumerate(top_scores):
 8         print("Parameters with rank: {0}".format(i + 1))
 9         print("Mean validation score: {0:.4f} (std: {1:.4f})".format(
10               score.mean_validation_score, np.std(score.cv_validation_scores)))
11         print("Parameters: {0}".format(score.parameters))
12         print("")
13         
14         if params == None:
15             params = score.parameters
16     
17     return params
18 # Simple grid test
19 grid_test1 = { "n_estimators"      : [1000, 2500, 5000],
20                "criterion"         : ["gini", "entropy"],
21                "max_features"      : [sqrtfeat-1, sqrtfeat, sqrtfeat+1],
22                "max_depth"         : [5, 10, 25],
23                "min_samples_split" : [2, 5, 10,minsampsplit ] }
24 
25 forest = RandomForestClassifier(oob_score=True)
26  
27 print "Hyperparameter optimization using GridSearchCV..."
28 grid_search = GridSearchCV(forest, grid_test1, n_jobs=-1, cv=10)
29 grid_search.fit(X, y)
30 best_params_from_grid_search = scorereport.report(grid_search.grid_scores_)

經訓練得到的參數為    params_score = { "n_estimators"      : 10000,   "max_features"      : sqrtfeat,   "min_samples_split" : minsampsplit },結果還是很符合經驗結果預測的。

怎么評價這個訓練后的模型呢? Learning Curves。《機器學習實戰》這本書里有講,Andrew Ng的公開課里也講過。主要是偏差方差折衷與測試誤差和訓練誤差的關系。我們應該調整模型來達到測試誤差的最小值。sklearn.learning_curve模塊可以完成這個功能。 Learning Curves曲線最后表明我們的模型需要更多的數據訓練。

在訓練時要注意的是,因為幸存者相對未幸存的人數較少,所以數據是不均衡的,可以通過上抽樣或下抽樣或者調整樣本的權重,來獲得均衡的訓練樣本。

然后我們就可以用forest來預測測試集了,bingo!




免責聲明!

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



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