『應用機器學習的建議』的學習筆記

mathshelly發表於2015-04-12

這篇文章是以Bremen大學機器學習課程的教程為基礎的。本文總結了使用機器學習解決新問題的一些建議。包括:

  • 視覺化資料的方法
  • 選擇一個適合當前問題的機器學習方法
  • 鑑別和解決過擬合和欠擬合問題
  •  處理大資料庫問題(注意:不是非常小的)
  •  不同損失函式的利弊

本文以Andrew Ng的《應用機器學習的建議 | Advice for applying Machine Learning》為基礎。這個筆記的目的是用一個互動的方法解釋這些觀點。有些建議是可以討論的。它們僅是建議,不是嚴格的規則。

In [1]:

In [2]:

In [3] :

資料集

我們使用sklearn的make_classification函式來生成一些簡單的玩具資料:

In [4] :

注意到我們為二分類生成了一個資料集,這個資料集包括1000個資料點,每個特徵20維。我們已經使用pandas的DataFrame類把資料和類別封裝到一個共同的資料結構中。我們來看一看前5個資料點:

In [5]:

Out[5]:

通過直接檢視原始特徵值,我們很難獲得該問題的任何線索,即使在這個低維的例子中。因此,有很多的提供資料的更容易檢視的方法;其中的小部分將在接下來的部分中討論。

視覺化

當你接到一個新的問題,第一步幾乎都是視覺化,也就是說,觀察你的資料。

Seaborn是一個不錯的統計資料視覺化包。我們使用它的一些函式來探索資料。

第一步是使用pairplot生成散點圖和直方圖。兩種顏色對應了兩個類別,我們使用了特徵的一個子集、僅僅使用前50個資料點來簡化問題。

In [6] :

基於該直方圖,我們可以看到一些特徵比其他特徵對分類更有用。特別地,特徵11和14看起來有豐富的資訊量。這兩個特徵的散點圖顯示類別在二維空間中幾乎是線性可分的。要更加註意的是,特徵12和19是高度負相關的。我們可以通過使用corrplot更系統地探索相關性:

In [7] :

我們可以發現我們之前的觀察結果在這裡得到了確認:特徵11和14與類強相關(他們有豐富的資訊量)。更進一步,特徵12和特徵19強負相關,特徵19和特徵14強相關。因此,有一些特徵是冗餘的。這對於有些分類器可能會出現問題,比如,樸素貝葉斯,它假設所有的特徵都是獨立的。剩下的特徵大部分都是噪聲,他們既不相互關聯,也不和類別相關。

注意到如果特徵維數較大、資料點較少的時候,資料視覺化會變得更有挑戰性。我們在後面會給出一個高維資料視覺化的例子。

方法的選擇

一旦我們已經使用視覺化方法對資料進行了探索,我們就可以開始應用機器學習了。機器學習方法數量眾多,通常很難決定先嚐試哪種方法。這個簡單的備忘單(歸功於Andreas Müllersklearn團隊)可以幫助你為你的問題選擇一個合適的機器學習方法(供選擇的備忘錄見
http://dlib.net/ml_guide.svg

In [8] :

Out[8] :

我們有了1000個樣本,要預測一個類別,並且有了標籤,那麼備忘單推薦我們首先使用LinearSVC(LinearSVC代表線性核的支援向量分類,並且對於這類特殊問題使用一個有效的演算法)。所有我們做了個試驗。LinearSVC需要選擇正則化;我們使用標準L2範數懲罰和C=10.我們分別畫出訓練分數和驗證分數的學習曲線(這個例子中分數代表準確率):

In [9] :

我們可以注意到訓練資料和交叉驗證資料的錯誤率有很大的差距。這意味什麼?我們可能過度擬合訓練資料了!

解決過擬合

有很多方法來減少過擬合:

  • 增加訓練樣本數

(獲得更多的資料是機器學習從業者的共同願望)

In [10] :

可以看到當訓練資料增加時,驗證分數越來越大,差距越來越小;因此現在不再過擬合了。有很多獲得更多資料的方法,比如(a)可以盡力投資收集更多資料,(b)基於現有資料創造一些人為的資料(比如影象旋轉,平移,扭曲),或者(c)加入人工噪聲。

如果以上的這些方法都不可行,就不可能獲得更多的資料,我們或者可以

  • 減少特徵的維數

(從我們視覺化中可以知道,特徵11和14是資訊量最大的)

In [11] :

注意到,因為我們是手動的挑選特徵,而且在比我們給分類器更多的資料上,這有一點作弊的意味。我們可以使用自動挑選特徵:

In [12] :

這樣做效果非常好。在這個toy資料集上,特徵選擇是簡單的。應該注意到特徵選擇只是減少模型複雜度的一個特殊種類。其他的方法是:(a)減少線性迴歸多項式模型的次數,(b)減少人工神經網路節點的個數/層數,(c)增加RBF核的頻寬等等。

仍然有一個問題:為什麼分類器不能自動的識別有用的特徵?首先讓我們轉向另一種選擇,來減少過擬合:

  • 增加分類器的正則化

(減少線性SVC的C的係數)

In [13] :

這已經有一點點作用了。我們也可以使用基於交叉驗證的網格搜尋自動地挑選分類器的正則化:

In [14] :

在100個資料點上選擇引數:{‘C’: 0.01}

一般說來,特徵選擇似乎更好。分類器可以自動識別有用的特徵嗎?回想一下,LinearSVC還支援L1範數懲罰,這產生了一個稀疏的解決方案。稀疏解決方案對應一個隱式的特徵選擇。讓我們來試試這個:

In [15] :

這看起來也很好。讓我們來探討學到的係數:

In [16] :

Coefficients learned: [[ 0. 0. 0. 0. 0. 0.01857999
0. 0. 0. 0.004135 0. 1.05241369
0.01971419 0. 0. 0. 0. -0.05665314
0.14106505 0. ]]
Non-zero coefficients: [ 5 9 11 12 17 18]

大部分系數是0(對應的特徵被忽略),並且目前最大的權重在特徵11上。

不同的資料集

我們生成另外一個二分類的資料集,並且再次應用LinearSVC。

In [17]:

In [18]:


啊,這非常糟糕,甚至訓練誤差都不如隨機誤差。這個可能的原因是什麼?難道上面的所有方法(更多資料,特徵選擇,增加正則化)都不奏效了嗎?

結果是:No。我們處在一個完全不同的情況:以前,訓練分數一直接近完美,我們不得不解決過擬合。這次,訓練誤差也非常低。是欠擬合。讓我們來看一看資料:

In [19] :

這些資料顯然不是線性可分的;更多的資料或者更少的特徵沒有用了。我們的模型錯了;因此欠擬合。

解決欠擬合

減少欠擬合的方法:

  • 使用更多或更好的特徵(到原點的距離應該有用!)

In [20] :

非常好!但是我們必須要花一些心思來想出這些特徵。或許分類器可以自動的做到這些?這需要

  • 使用更復雜的模型

(減少正則化或非線性核)

In [21] :

是的,這也可以達到滿意的效果!

更大的資料集和更高維的特徵空間

回到原始的資料集上,但是這次有更多的特徵和樣本,並且有5類。LinearSVC在這樣大小的資料集上會有一點慢;備忘單上建議使用SGDClassifier。這個分類器學習到一個線性模型(就像LinearSVC或logistic迴歸),但是它在訓練中使用隨機梯度下降(就像反向傳播的人工神經網路一樣)。

SGDClassifier允許小批量掃描資料,這對於資料量太大不能放到記憶體中時有幫助。交叉驗證和這項技術不相容;使用逐步驗證代替:這裡,估計器總是在訓練資料集的下一塊上進行測試(在用它進行訓練之前)。訓練之後,會再次進行測試來檢查它適應資料的能力。

In [22] :

In [23]:

Out[23]:

這個圖告訴我們,在50個mini-batches的資料之後,我們已經不能再提高驗證資料了,因此可以停止訓練了。由於訓練分數不是很高,我們可能是欠擬合而不是過擬合。要是使用rbf核測試一下就更好了,但是SGDClassifier很不幸的不相容核技巧。替代方法是可以使用一個多層的感知機,它也可以使用隨機梯度下降進行訓練,但是一個非線性模型,或者像備忘單建議的,使用核近似法。

現在在一個機器學習中使用的經典的解決光學字元識別的資料集上:

In [24]:

由1083個樣本組成的資料集,每個樣本由64個特徵組成

因此我們有1083個手寫數字(0,1,2,3,4,5)樣本,每一個樣本由8*8的4bit畫素(0,16)灰度圖片組成。因此特徵的維數適中(64);但是,這64維空間的視覺化是非常重要的。我們來說明不同的減少維數(至二維)方法,基於http://scikit-learn.org/stable/auto_examples/manifold/plot_lle_digits.html#example-manifold-plot-lle-digits-py

In [25]:

已經隨機投影的二維資料的結果不是太差:

In [26]:

然而,有一個很著名的方法一般來說應該適合,也就是PCA(使用TruncatedSVD來實現,不需要構建協方差矩陣):

In [27]:

PCA給出一個更好的結果,而且在這個資料集上甚至更快。通過允許64維輸入空間到二維目標空間的非線性變換,我們可以得到更好的結果。這有很多種方法;我們這裡只介紹一種方法:t-SNE。

In [28]:

這是一個非常優秀的嵌入,也表明只使用一個分類器完美地分開這些類是可能的(詳見例子http://scikit-learn.org/stable/auto_examples/plot_digits_classification.html)。t-SNE唯一的不足是它需要更多的時間來計算,因此不適用於大資料集(在目前的條件下)

損失函式的選擇

損失函式的選擇也非常重要。下面是不同損失函式的說明:
In [29]:

Out[29]:

不同的損失函式有不同的優勢:

  • 0-1損失是在分類問題中你實際上需要的。不幸地是,這是非凸優化問題,由於最優化問題會變得或多或少的不好解決,因此並不實用。
  • 合頁損失(使用支援向量分類)匯出一個在資料中稀疏的解(由於$f(x) > 1$,它變為0),而且對離群點比較穩健(由於$f(x)to-infty$,它僅僅成線性增長)。它不提供充分的校準的概率
  • 對數損失函式(比如,在邏輯迴歸中使用)匯出很好的概率校準。因此,如果你不僅得到二值預測,還可以得出結果的概率,這個損失函式是一個很好的選擇。缺點是,它的解在資料空間中是不稀疏的,它比合頁損失函式更容易受到離群點的影響。
  • 指數損失函式(在Adaboost中使用)非常容易受離群點的影響(由於當$f(x)to-infty$時它快速增加)。它主要適用於Adaboost中,因為它在一個簡單有效的boosting演算法中有效果。
  • 感知器損失函式基本上是合頁損失函式的移動版本。合頁損失函式也懲罰非常接近邊界但是在正確一邊的點(間隔最大化準則)。另一方面,感知器損失函式只要資料點在邊界正確的一邊就可以,如果資料是線性可分就使得邊界待定,導致比間隔最大化更差的泛化性。

總結

以上我們討論了一些怎麼讓機器學習在一個新的問題上工作起來的建議。我們考慮了分類問題,迴歸和聚類問題也與之類似。然而,專注於人工資料集(為了便於理解)還有點過於簡單化。在很多實際問題中,資料的收集、組織、預處理是極重要的。請參見本文中data wrangling的例子。Pandas是這方面很好的工具。

很多應用領域也有具體要求,也有符合這些要求的工具,比如:

  • 使用skimage圖片處理
  • 使用pySPACE的生物訊號分析和一般時間序列處理
  • 使用pandas處理財務資料

我們不詳細探索這些領域;然而,尋找一個好的預處理流程往往比選擇一個合適的分類器需要付出更大的努力。我們可以通過一個例子初識一箇中等複雜的訊號處理流程,該例中使用pySPACE在腦電波資料中檢測特定事件相關電位:
https://github.com/pyspace/pyspace/blob/master/docs/examples/specs/node_chains/ref_P300_flow.yaml

訊號處理流程包含資料標準化,抽取,帶通濾波,降維(xDAWN是一個監督的降維方法),特徵提取(區域性直線特徵),和特徵標準化。下圖給出了pySPACE中分類之前可用的流程各部分的一個概貌。

In [30]:

Out[30]:

機器學習的一個長遠目標,也是深度學習領域的追求,是可以學習大部分這樣的流程,而不是手工編寫它們。

In [31]:

Jan Hendrik Metzen 29/01/2015

CPython 2.7.9
IPython 2.1.0

numpy 1.9.1
scikit-learn 0.14.1

compiler : GCC 4.4.7 20120313 (Red Hat 4.4.7-1)
system : Linux
release : 3.16.0-28-generic
machine : x86_64
processor : x86_64
CPU cores : 4
interpreter: 64bit

這篇文章是一篇IPython筆記。你可以下載該筆記。

相關文章