閱讀891 返回首頁    go 阿裏雲 go 技術社區[雲棲]


解決機器學習問題有通法!看這一篇就夠了!

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

大數據文摘作品

作者:Abhishek Thakur

編譯:Cathy,黃文暢,薑範波,寒小陽

前言

本文由Searchmetrics公司高級數據科學家Abhishek Thakur提供。

一個中等水平的數據科學家每天都要處理大量的數據。一些人說超過60%到70%的時間都用於數據清理、數據處理及格式轉化,以便於在之後應用機器學習模型。這篇文章的重點便在後者—— 應用機器學習模型(包括預處理的階段)。此文討論到的內容來源於我參加的過的數百次的機器學習競賽。請大家注意這裏討論的方法是大體上適用的,當然還有很多被專業人士使用的非常複雜的方法。

接下來會使用到python。

數據

在應用機器學習模型之前,所有的數據都必須轉換為表格形式。如下圖所示,這個過程是最耗時、最困難的部分。

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

轉換完成之後,便可以將這些表格數據灌入機器學習模型。表格數據是在機器學習或是數據挖掘中最常見的數據表示形式。我們有一個數據表,x軸是樣本數據,y軸是標簽。標簽可以是單列可以是多列,取決於問題的形式。我們會用X表示數據,y表示標簽。


標簽的種類

標簽會定義你要解決何種問題,有不同的問題類型。例如:

單列,二進製值(分類問題,一個樣本僅屬於一個類,並且隻有兩個類)
單列,實數值(回歸問題,隻預測一個值)
多列,二進製值(分類問題,一個樣本屬於一個類,但有兩個以上的類)
多列,實數值(回歸問題,多個值的預測)
多個標簽(分類問題,一個樣本可以屬於幾個類)


評估指標

對於任何類型的機器學習問題,我們都一定要知道如何評估結果,或者說評估指標和目的是什麼。舉例來說,對於不均衡的二進製分類問題,我們通常選擇受試者工作特征曲線下麵積(ROC AUC或簡單的AUC);對於多標簽或多類別的分類問題,我們通常選擇分類交叉熵或多類對數損失;對於回歸問題,則會選擇均方差。

我不會再深入的講解不同的評估指標,因為根據問題的不同會有很多不同的種類。


開始嚐試機器學習庫可以從安裝最基礎也是最重要的開始,像numpy和scipy。

查看和執行數據操作:pandas(https://pandas.pydata.org/)
對於各種機器學習模型:scikit-learn(https://scikit-learn.org/stable/)
最好的gradient boosting庫:xgboost(https://github.com/dmlc/xgboost)
對於神經網絡:keras(https://keras.io/)
數據繪圖:matplotlib(https://matplotlib.org/)

監視進度:tqdm(https://pypi.python.org/pypi/tqdm)


Anaconda操作簡單而且幫你準備好了這些,可是我沒有使用,因為我習慣自己配置和自由使用。當然,決策在你手中。


機器學習總體框架

2015起,我開始製作一個自動機器學習框架,還在完善過程中,很快就會發布。下圖所示的框架圖就是這篇文章中將會提到的基礎框架:

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

圖片來源:A. Thakur and A. Krohn-Grimberghe, AutoCompete: A Framework for Machine Learning Competitions, AutoML Workshop, International Conference on Machine Learning 2015 


上麵的框架圖中,粉色的線代表最常用的路徑。結束提取數據並將其轉化為表格形式,我們就可以開始建造機器學習模型了。

第一步是識別(區分)問題。這個可以通過觀察標簽解決。你一定要知道這個問題是二元分類,還是多種類或多標簽分類,還是一個回歸問題。當識別了問題之後,就可以把數據分成訓練集和測驗集兩個部分。如下圖所示。 

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


將數據分成訓練集和驗證集“必須”根據標簽進行。遇到分類問題,使用分層分割就對了。在Python中,用scikit-learn很容易就做到了。

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

遇到回歸問題,一個簡單的K-Fold分割就可以了。當然,也還有很多複雜的方法能夠在維持訓練集和驗證集原有分布的同時將數據分割開來。這個就留給讀者們自己去練習啦。 

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

相關閱讀: Startup Lessons: This Is Why You Need To Move Quickly

在以上的例子中我選擇用全數據的10%作為驗證集,當然你可以根據手中具體的數據決定取樣的大小。 

分好數據之後,就可以把它放在一邊不要碰了。任何作用於訓練集的運算都必須被保存並應用於驗證集。驗證集無論如何都不可以和訓練集混為一談。因為混到一起之後雖然回到一個讓用戶滿意的評估指標值,但卻會因為模型過擬合而不能使用。 

下一步是識別數據中不同的變量。通常有三種變量:數值變量、分類變量和文本變量。讓我們用很受歡迎的關於泰坦尼克號的數據集來舉個例子。 
(https://www.kaggle.com/c/titanic/data).

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

在這裏,“survival”(生存)就是標簽。在前一個步驟中我們已經把標簽從訓練集中去掉了。接下來,有pclass,sex, embarked變量這些變量由不同的級別,因此是分類變量。像age, sibsp, parch等就是數值變量。Name是一個含有文本的變量,但我不認為它對預測是否生存有用。

先把數值變量分離出來。這些變量不需要任何形式的處理,所以我們可以開始對其歸一並應用機器學習模型。

處理分類變量有兩種變法:

把分類變量轉化為標簽  

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

把標簽轉化為二進製變量  

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=


請記住在應用OneHotEncoder之前要用LabelEncoder把分類變量轉化為數值變量。

既然泰坦尼克數據裏麵沒有好的關於文本變量的例子,我們就自己製定一個處理文本變量的一般規則。我們可以把所有文本變量整合在一起然後用一些文本分析的算法把他們轉換成數字。

文本變量可以如下這樣整合: 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

然後就可以應用CoutVectorizer或者TfidfVectorizer在上麵啦: 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

或者

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

TfidfVectorizer大多數時候比單純計數效果要好。下麵的參數設置在大多數時候都有很好的結果。

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

如果你在訓練集上做了向量化處理(或者其他操作),請確保將其(相應的處理)轉存在硬盤上,以便以後在驗證集上應用。

640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

接下來,就是堆疊器模塊。堆疊器模塊不是模型堆疊而是特征堆疊。上述處理步驟之後得到的不同特征可以通過堆疊器模塊整合到一起。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

你可以水平地堆疊所有的特征,然後通過使用numpy hstack或sparse hvstack進行進一步處理,具體取決於是否具有密集或稀疏特征。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

也可以通過FeatureUnion模塊實現,以防萬一有其他處理步驟,如PCA或特征選擇(我們將在後文提到分解和特征選擇)。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

一旦我們把特征找齊了,就可以開始應用機器學習模型了。在這個階段,你隻需用到基於樹的模型,包括:

隨機森林分類器
隨機森林回歸器
ExtraTrees分類器
ExtraTrees回歸器
XGB分類器
XGB回歸器  

由於沒有歸一化,我們不能將線性模型應用到上述特征上。為了能夠應用線性模型,可以從scikit-learn中使用Normalizer或者StandardScaler。

這些歸一化的方法僅限於密集特征,對稀疏特征,結果差強人意。當然,也可以在不使用平均值(參數:with_mean=False)的情況下對稀疏矩陣使用StandardScaler。

如果以上步驟得到了一個“好的”模型,我們就可以進一步做超參數的優化了。得不到的情況下,可以做如下步驟以改進模型。

接下來的步驟包括分解模型: 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

簡潔起見,我們跳過LDA和QDA轉化。對高維數據,一般而言,PCA可以用來分解數據。對圖片而言,從10-15個組分起始,在結果質量持續改進的前提下,逐漸增加組分數量。對其它的數據而言,我們挑選50-60個組分作為起點(對於數字型的數據,隻要我們能夠處理得了,就不用PCA) 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

對文本型的數據,把文本轉化為稀疏矩陣後,進行奇異值分解(Singular Value Decomposition (SVD)),可以在scikit-learn中找到一個SVD的變異版叫做TruncatedSVD。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

一般對TF-IDF有效的奇異值分解成分(components)是120-200個。更多的數量可能效果會有所改進但不是很明顯,而計算機資源耗費卻很多。

在進一步評價模型的性能以後,我們可以再做數據集的縮放,這樣就可以評價線性模型了。歸一化或者縮放後的特征可以用在機器學習模型上或者特征選擇模塊裏。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

特征選擇有很多方法。最常用的方法之一是貪心算法選擇(正向或反向)。具體而言,選擇一個特征,在一個固定的評價矩陣上訓練一個模型,評價其性能,然後一個一個地往裏麵增加或移除特征,記錄每一步的模型性能。最後選擇性能得分最高時的那些特征。貪心算法和其評價矩陣的AUC的一個例子見鏈接: https://github.com/abhishekkrthakur/greedyFeatureSelection。 
需要注意的是,這個應用並非完美,必須根據要求進行修改。

其他更快的特征選擇方法包括從一個模型中選取最好的特征。我們可以根據一個邏輯回歸模型的係數,或者訓練一個隨機森林來選擇最好的特征,然後把它們用在其它的機器學習模型裏。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

記得把估計值或者超參數的數量控製得盡量少,這樣你才不會過擬合。

用Gradient Boosting Machine也可以實現特征選擇。如果能用xgboost就不要用GBM,因為前者要快得多,可擴展性更好。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

對稀疏數據集,也可以用隨機森林分類器/隨機森林回歸器或xgboost做特征選擇。

從正性稀疏數據集裏選擇特征的其它流行方法還有基於卡方的特征選擇,scikit-learn中即可應用。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

這裏,我們用卡方聯合SelectKBest的方法從數據中選擇了20個特征。這個本身也是我們改進機器學習模型的超參數之一。

別忘了把任何中間過程產生的轉化體轉存起來。在驗證集上你會要用它們來評價性能。

下一步(或者說,緊接著)主要的步驟是模型選擇+超參數優化。 

一般來說,我們用下麵的算法來選擇機器學習模型:

分類
隨機森林
GBM
邏輯回歸
樸素貝葉斯
支持向量機

K最近鄰法


回歸
隨機森林
GBM
線性回歸
Ridge
Lasso
SVR

我需要優化哪個參數?如何選擇最好的參數?這些是人們經常會遇到的問題。沒有大量數據集上不同模型+參數的經驗,無法得到這些問題的答案。有經驗的人又不願意把他們的秘訣公之於眾。幸運的是,我有豐富的經驗,同時願意分享。讓我們來看看不同模型下超參數的秘密: 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

RS* =不好說合適的值是多少,在這些超參數裏隨機搜索一下。

以我個人淺見(原文作者個人意見),上述的這些模型比其他模型好,無需評價其它模型。

再說一次,記得保存這些轉化體: 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

然後對驗證集做相同的操作。 
640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=

上麵的規則和框架對我遇到的數據集而言運行良好。當然,在特別複雜的情況下也失敗過。天下沒有完美的東西,我們隻能在學習中不斷改進,如同機器學習一樣。

原文發布時間為:2017-09-18

本文作者:Abhishek Thakur

本文來自雲棲社區合作夥伴“大數據文摘”,了解相關信息可以關注“大數據文摘”微信公眾號



最後更新:2017-09-19 17:03:08

  上一篇:go  幹貨 | Active Learning: 一個降低深度學習時間,空間,經濟成本的解決方案
  下一篇:go  北京老字號:誰是互聯網時代的“網紅”?