天天看點

機器學習三人行(系列三)---End-to-End機器學習模組化

原文連結:閱讀原文

歡迎大家關注微信公衆号“智能算法”,我們一起學習,共同進步。 系列二我們詳細介紹了資料下載下傳,資料透析以及資料的不同分組方式,詳情請戳我!。但是在真正進行訓練之前,我們還需要對資料進行一個預處理。因為有些資料有一些缺失,以及怎麼處理分類變量,歸一化之類的操作,這樣算法才能夠表現出更好的性能。通常預處理有以下幾個步驟:缺失值和離群值處理(看情況),特征表征(使模型了解資料),歸一化,那麼我們接着系列二一起繼續學習。

一、資料清洗 再次觀察資料集,通過housing.shape,可以檢視資料集大小 (16512, 13),資料集的特征 如下:

機器學習三人行(系列三)---End-to-End機器學習模組化

發現 totals_rooms和bedrooms_per_room存在資料缺失的情況,由于一些機器學習算法無法計算缺失資料,是以需要對缺失值适當的處理工作。 1.1 缺失值處理 常用處理方法:對丢棄包含缺失值的行或列、對缺失值進行填充。我們來檢視缺失的占比情況:

機器學習三人行(系列三)---End-to-End機器學習模組化

發現隻有少部分缺失,是以丢棄行或列是不合适的,不然會損失有用的資訊,是以考慮對缺失值進行填充,而填充又包含填充中位數,衆數,均值,常量值(如-1),多值插補或通過模組化對缺失值進行預測等方法。考慮本例隻有少部分缺失值,是以使用中位數填充,方法: from sklearn.preprocessing import Imputer imputer = Imputer(strategy="median") imputer.fit(housing_num) 考慮中位數填充缺失值隻能對數值處理,對object的 ocean_proximity是無效的。是以将數值型相關特征從資料集中抽出來,housing_num = housing.drop('ocean_proximity', axis=1)。 接下來可以對housing_num做缺失值處理了,X = imputer.transform(housing_num) ,X就是處理後的結果生成一個新的dataframe,如下: housing_tr = pd.DataFrame(X, columns=housing_num.columns, index = list(housing.index.values)) 檢視生成housing_tr的處理後結果。

機器學習三人行(系列三)---End-to-End機器學習模組化

2.2 分類變量 housing資料集中唯一的分類特征ocean_proximity,将ocean_proximity特征拿出來處理,housing_cat = housing['ocean_proximity'],檢視類别的構成如下:

機器學習三人行(系列三)---End-to-End機器學習模組化

由于機器學習算法是沒有辦法了解字元的分類變量的,是以需要将字元的分類特征轉換成數值型分類特征,我們采用pandas中factorize()來完成轉換

機器學習三人行(系列三)---End-to-End機器學習模組化

雖然完成數值型分類特征的轉換,但是這樣處理會引入一個問題,轉換的分類變量變成有序和可比較了,即,轉換後的0,1,2,3,4,是不是能說0,1變量的距離和1,2的距離是一樣的。這樣明顯和原來的分類的特性是不符合的,要消除這個問題,需要使用OneHotEncoder來處理。

機器學習三人行(系列三)---End-to-End機器學習模組化

其實上面的從factorize到One-Hot encode可以使用sklearn.preprocessing.LabelBinarizer一步完成

機器學習三人行(系列三)---End-to-End機器學習模組化

是以類似One-Hot也會存在一個問題,如果分類變量的類别過多時,會導緻出現次元災難。 2.3 特征歸一化 由于特征不同的分布範圍,對一些算法尋優速度和收斂有影響,比如SVM,是以再進入模型前需要對特征進行歸一化,常用的歸一化有:Min-Max Scaling和Z-Score Standardization兩種。分别對應sklearn中MinMaxScaler和StandardScaler方法。而且StandardScaler更多是應用在特征存在偏态分布的情況下,根據系列二中特征的分布情況,這裡采用StandardScaler進行特征歸一化。

機器學習三人行(系列三)---End-to-End機器學習模組化

二、pipeline流水線 通過上面的處理,我們已經對資料進行了基本的資料清洗工作,我們可以拿上面處理好的資料直接進行模組化了,但是這裡會面臨兩個問題:一個是我們是把數值型特征和分類型特征分别處理的,是以需要合并,二是後面對于驗證集的預測前,驗證資料集需要按照的處理流程重新跑一遍,才能進行預測,就需要将訓練集的一些特殊的處理過程儲存,應用到驗證集和測試集的處理上。 想想如果需要對訓練集的處理方法修改的話,将是更加麻煩的事情,這裡就需要引入了sklearn中一個強大的工具,pipeline,把我們的處理過程流水線化,對驗證集和測試集上調用fit、transform就可以完成處理,然後扔到模型中去預測,而且配合FeatureUnion還可以完成并行處理。過程大緻如下:

機器學習三人行(系列三)---End-to-End機器學習模組化

2.1 自定義方法 sklearn的pipeline要完成流程化處理,調用的函數必須包含三種方法:fit(),transform(),和fit_transform。而且是隻要包含這三種方法都可以放到pipeline中去,也就是說,我們可以自己寫方法,隻需要定義好這三個方法就可以了,最後一個fit_transform方法,隻需要通過繼承TransformerMixin方法就可以獲得,是以隻需要我們定義fit和transform方法就可以了,可以把系列二中特征融合自己定義一個pipeline方法:

機器學習三人行(系列三)---End-to-End機器學習模組化

attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False) housing_extra_attribs = attr_adder.transform(housing.values) 通過上面調用測試方法是否可用。 2.2 sklearn可用方法 sklearn本身包含了豐富的預處理和特征處理的方法,比如在預進行中使用到的StandardScaler,Imputer等,下面列舉了一些sklearn常用的處理方法,更多内容可以檢視sklearn的官網:

機器學習三人行(系列三)---End-to-End機器學習模組化

2.3 本文使用方法 通過上面的方法可以完成将前面對數值型特征的處理寫成一個pipeline:

機器學習三人行(系列三)---End-to-End機器學習模組化

由于我們的處理分成的數值型特征處理和分類特征的處理兩部分,如果寫成兩個pipeline來分别處理的話,最後需要将結果合并,還是太麻煩了,是以我們還需要一個對選擇資料集的pipeline處理方法:

機器學習三人行(系列三)---End-to-End機器學習模組化

有了DataframeSelector方法,我們通過FeatureUnion的并行化處理來寫一個完整的pipeline處理流程如下:

機器學習三人行(系列三)---End-to-End機器學習模組化

通過調用:housing_prepared = full_pipeline.fit_transform(housing)完成全部的處理過程。

三、建立模型 3.1 基準模型 通過上面full_pipeline,資料的預處理已經完成,接下來利用處理好的資料建立模型,我們選擇簡單的線性回歸,作為基準模型,後續在此基礎上不斷優化模型效果。 from sklearn.linear_model import LinearRegression lin_reg = LinearRegression() lin_reg.fit(housing_prepared, housing_labels) 我們嘗試取原資料前五條資料來預測,觀測效果 some_data = housing.iloc[:5] some_labels = housing_labels.iloc[:5] some_data_prepared = full_pipeline.transform(some_data) print("Predictions:", lin_reg.predict(some_data_prepared)) 預測結果: Predictions: [ 210644.60459286 317768.80697211 210956.43331178 59218.98886849 189747.55849879] 而原資料的實際值為: Actual: [286600.0, 340600.0, 196900.0, 46300.0, 254500.0] 對于回歸問題,常用的評估名額有均方根誤差(RMSE),平均絕對內插補點(MAE),RMSE在可以使用sklearn的mean_squared_error計算,MAE對應mean_absolute_error。對測試的預測值計算評估名額結果如下:

機器學習三人行(系列三)---End-to-End機器學習模組化
機器學習三人行(系列三)---End-to-End機器學習模組化

在此基礎上可以嘗試各種不同的模型,通過比較評估名額,擷取最合适的模型,作為最終的模組化模型,當然上面的評估隻是作為模型預測的測試,實際中我們需要将資料集劃分出訓練集和驗證集,通過交叉驗證的方法來評估。 3.2交叉驗證 交叉驗證,可以使用sklearn的cross_val_score來完成,計算之前先寫一個結果的展示函數,友善檢視結果: def display_scores(scores): print("Scores:", scores) print("Mean:", scores.mean()) print("Standard deviation:", scores.std()) 接下來我們通過建立随機森林來,通過交叉驗證來評估模型效果; 構模組化型:

機器學習三人行(系列三)---End-to-End機器學習模組化

效果評估:

機器學習三人行(系列三)---End-to-End機器學習模組化

通過10折交叉驗證,得到最終的平均RMSE值:52564.19。通過類似方法可以比較不同的模型的預測效果。

四、參數調整 當我們使用機器學習算法時,會發現幾乎所有的算法都包括一些超參數, 這些參數和正常參數不同,它們不是模型的一部分,不會在模型拟合中被自動調整。它們是在另外的步驟中被調整的。一些超參數的例子,包括在嶺回歸和lasso回歸中的正則項lambda、支援向量機中的C項、基于樹的算法中樹的數量(如,随機森林、梯度提升機)。 常用的超參數優化方法有:網格搜尋,随機搜尋,貝葉斯優化,sklearn已經為我們提供了網格搜尋和随機搜尋的方法實作,貝葉斯優化也有一些的實作包,而且貝葉斯優化在一些資料挖掘競賽kaggle中用的比較多。 4.1. 網格搜尋 網格搜尋是在我們預先設定的參數的不同超參數取值中,組成出最優結果的超參數方法,如對上面的随機森林算法尋找最優參數

機器學習三人行(系列三)---End-to-End機器學習模組化

上面的網格搜尋會對12種n_estimators和max_features的組合模組化和6種boostrap的參數組合來尋找最優參數,也就是系統會自動建立18個模型,自動比較出最優的參數,最後通過grid_search.best_params_可以檢視最優的模型參數。 4.2. 随機搜尋 随機搜尋的思想和網格搜尋比較相似,隻是不再搜尋上界和下界之間的所有值,隻是在搜尋範圍中随機取樣本點。它的理論依據是,如果随即樣本點集足夠大,那麼也可以找到全局的最大或最小值,或它們的近似值。通過對搜尋範圍的随機取樣,随機搜尋一般會比網格搜尋要快一些。但是和網格搜尋的快速版(非自動版)相似,結果也是沒法保證的。下面通過随機搜尋來尋找最優參數。

機器學習三人行(系列三)---End-to-End機器學習模組化

使用随機搜尋還有一個好處是我們可以設定搜尋疊代的次數來控制對調參的資源配置設定。 4.3. 貝葉斯優化 貝葉斯優化尋找使全局達到最值的參數時,使用了和網格搜尋、随機搜尋完全不同的方法。網格搜尋和随機搜尋在測試一個新的點時,會忽略前一個點的資訊。而貝葉斯優化充分利用了這個資訊。貝葉斯優化的工作方式是通過對目标函數形狀的學習,找到使結果向全局最大值提升的參數。它學習目标函數形狀的方法是,根據先驗分布,假設一個搜集函數。在每一次使用新的采樣點來測試目标函數時,它使用這個資訊來更新目标函數的先驗分布。然後,算法測試由後驗分布給出的,全局最值最可能出現的位置的點。關于貝葉斯優化的原理可以在公衆号中回複"貝葉斯優化",可以擷取到相關論文。 關于該方法的調參在github上已經有人根據論文内容,把算法實作了,而且在kaggle比賽中得到廣泛使用。它的python包名叫bayes_opt。可以通過pip install bayesian-optimization來安裝。安裝成功後可以使用bayes_opt來進行參數優化,使用執行個體如下:

機器學習三人行(系列三)---End-to-End機器學習模組化

通過robf.maximize(n_iter=10)檢視優化過程并擷取最優值,由于bayes_opt隻能求最大值,是以rfccv輸出需要轉換成10000/np.sqrt(-val)。 對于貝葉斯優化,一個主要需要注意的地方,是一旦它找到了一個局部最大值或最小值,它會在這個區域不斷采樣,是以它很容易陷入局部最值。為了減輕這個問題,貝葉斯優化算法會在勘探和開采(exploration and exploitation)中找到一個平衡點。勘探(exploration),就是在還未取樣的區域擷取采樣點。開采(exploitation),就是根據後驗分布,在最可能出現全局最值的區域進行采樣。

五、模型評估 通過模型的調參,擷取最優參數,利用最優參數建立我們最終的模型。前面我們是在訓練集和驗證集訓練得到最優模型,但是最終決定模型是否可用,是需要通過評估模型在測試集上的預測表現,這是我們的最終一步,通過比較模型在測試集的表現決定模型的效果,正常來說,測試集的表現會比驗證集上的表現稍差,但是差别不會太大,如果模型的預測差别很大的,那麼可能由兩個原因導緻:1、出現過拟合現象,2、測試集和驗證集特征分布有較大差别。是以需要從這兩個方面進行排查,另外,看到模型在測試集上效果不佳,千萬不要基于測試集來進行調參以達到模型在測試集上的表現,這樣并不能提高模型的泛化能力,而隻是測試集又變成了驗證集,再後續新的測試集上還是會出現同樣的問題。

(如需更好的了解相關知識,歡迎加入智能算法社群,在“智能算法”公衆号發送“社群”,即可加入算法微信群和QQ群)

機器學習三人行(系列三)---End-to-End機器學習模組化

繼續閱讀