天天看點

機器學習算法一覽

機器學習算法一覽

提起筆來寫這篇部落格,突然有點愧疚和尴尬。愧疚的是,工作雜事多,加之懶癌嚴重,導緻這個系列一直沒有更新,向關注該系列的同學們道個歉。尴尬的是,按理說,機器學習介紹與算法一覽應該放在最前面寫,詳細的應用建議應該在講完機器學習常用算法之後寫,突然莫名奇妙在中間插播這麼一篇,好像有點打亂主線。

老話說『亡羊補牢,為時未晚』,前面開頭忘講的東西,咱在這塊兒補上。我們先帶着大家過一遍傳統機器學習算法,基本思想和用途。把問題解決思路和方法應用建議提前到這裡的想法也很簡單,希望能提前給大家一些小建議,對于某些容易出錯的地方也先給大家打個預防針,這樣在了解後續相應機器學習算法之後,使用起來也有一定的章法。

按照不同的分類标準,可以把機器學習的算法做不同的分類。

我們先從機器學習問題本身分類的角度來看,我們可以分成下列類型的算法:

監督學習算法

機器學習中有一大部分的問題屬于<code>『監督學習』</code>的範疇,簡單口語化地說明,這類問題中,給定的訓練樣本中,每個樣本的輸入x都對應一個确定的結果y,我們需要訓練出一個模型(數學上看是一個x→y的映射關系f),在未知的樣本x′給定後,我們能對結果y′做出預測。

這裡的預測結果如果是離散值(很多時候是類别類型,比如郵件分類問題中的垃圾郵件/普通郵件,比如使用者會/不會購買某商品),那麼我們把它叫做分類問題(classification problem);如果預測結果是連續值(比如房價,股票價格等等),那麼我們把它叫做回歸問題(regression problem)。

有一系列的機器學習算法是用以解決監督學習問題的,比如最經典的用于分類問題的樸素貝葉斯、邏輯回歸、支援向量機等等;比如說用于回歸問題的線性回歸等等。

無監督學習

有另外一類問題,給我們的樣本并沒有給出『标簽/标準答案』,就是一系列的樣本。而我們需要做的事情是,在一些樣本中抽取出通用的規則。這叫做<code>『無監督學習』</code>。包括關聯規則和聚類算法在内的一系列機器學習算法都屬于這個範疇。

半監督學習

這類問題給出的訓練資料,有一部分有标簽,有一部分沒有标簽。我們想學習出資料組織結構的同時,也能做相應的預測。此類問題相對應的機器學習算法有自訓練(self-training)、直推學習(transductive learning)、生成式模型(generative model)等。

總體說來,最常見是前兩類問題,而對應前兩類問題的一些機器學習算法如下:

機器學習算法一覽

我們也可以從算法的共性(比如功能,運作方式)角度對機器學習算法分類。下面我們根據算法的共性去對它們歸個類。不過需要注意的是,我們下面的歸類方法可能對分類和回歸有比較強的傾向性,而這兩類問題也是最常遇到的。

機器學習算法一覽

回歸算法是一種通過最小化預測值與實際結果值之間的差距,而得到輸入特征之間的最佳組合方式的一類算法。對于連續值預測有線性回歸等,而對于離散值/類别預測,我們也可以把邏輯回歸等也視作回歸算法的一種,常見的回歸算法如下:

ordinary least squares regression (olsr)

linear regression

logistic regression

stepwise regression

locally estimated scatterplot smoothing (loess)

multivariate adaptive regression splines (mars)

機器學習算法一覽

這裡所謂的基于執行個體的算法,我指的是我們最後建成的模型,對原始資料樣本執行個體依舊有很強的依賴性。這類算法在做預測決策時,一般都是使用某類相似度準則,去比對待預測的樣本和原始樣本的相近度,再給出相應的預測結果。常見的基于執行個體的算法有:

k-nearest neighbour (knn)

learning vector quantization (lvq)

self-organizing map (som)

locally weighted learning (lwl)

機器學習算法一覽

決策樹類算法,會基于原始資料特征,建構一顆包含很多決策路徑的樹。預測階段選擇路徑進行決策。常見的決策樹算法包括:

classification and regression tree (cart)

iterative dichotomiser 3 (id3)

c4.5 and c5.0 (different versions of a powerful approach)

chi-squared automatic interaction detection (chaid)

m5

conditional decision trees

機器學習算法一覽

這裡說的貝葉斯類算法,指的是在分類和回歸問題中,隐含使用了貝葉斯原理的算法。包括:

naive bayes

gaussian naive bayes

multinomial naive bayes

averaged one-dependence estimators (aode)

bayesian belief network (bbn)

bayesian network (bn)

機器學習算法一覽

聚類算法做的事情是,把輸入樣本聚成圍繞一些中心的『資料團』,以發現資料分布結構的一些規律。常用的聚類算法包括:

k-means

hierarchical clustering

expectation maximisation (em)

機器學習算法一覽

關聯規則算法是這樣一類算法:它試圖抽取出,最能解釋觀察到的訓練樣本之間關聯關系的規則,也就是擷取一個事件和其他事件之間依賴或關聯的知識,常見的關聯規則算法有:

apriori algorithm

eclat algorithm

機器學習算法一覽

這是受人腦神經元工作方式啟發而構造的一類算法。需要提到的一點是,我把『深度學習』單拎出來了,這裡說的人工神經網絡偏向于更傳統的感覺算法,主要包括:

perceptron

back-propagation

radial basis function network (rbfn)

機器學習算法一覽

deep boltzmann machine (dbm)

deep belief networks (dbn)

convolutional neural network (cnn)

stacked auto-encoders

機器學習算法一覽

從某種程度上說,降維算法和聚類其實有點類似,因為它也在試圖發現原始訓練資料的固有結構,但是降維算法在試圖,用更少的資訊(更低維的資訊)總結和描述出原始資訊的大部分内容。

有意思的是,降維算法一般在資料的可視化,或者是降低資料計算空間有很大的作用。它作為一種機器學習的算法,很多時候用它先處理資料,再灌入别的機器學習算法學習。主要的降維算法包括:

principal component analysis (pca)

principal component regression (pcr)

partial least squares regression (plsr)

sammon mapping

multidimensional scaling (mds)

linear discriminant analysis (lda)

mixture discriminant analysis (mda)

quadratic discriminant analysis (qda)

flexible discriminant analysis (fda)

機器學習算法一覽

嚴格意義上來說,這不算是一種機器學習算法,而更像是一種優化手段/政策,它通常是結合多個簡單的弱機器學習算法,去做更可靠的決策。拿分類問題舉個例,直覺的了解,就是單個分類器的分類是可能出錯,不可靠的,但是如果多個分類器投票,那可靠度就會高很多。常用的模型融合增強方法包括:

random forest

boosting

bootstrapped aggregation (bagging)

adaboost

stacked generalization (blending)

gradient boosting machines (gbm)

gradient boosted regression trees (gbrt)

機器學習算法一覽

首先樣本量如果非常少的話,其實所有的機器學習算法都沒有辦法從裡面『學到』通用的規則和模式,so多弄點資料是王道。然後根據問題是有/無監督學習和連續值/離散值預測,分成了<code>分類</code>、<code>聚類</code>、<code>回歸</code>和<code>次元約減</code>四個方法類,每個類裡根據具體情況的不同,又有不同的處理方法。

上面帶着代價走馬觀花過了一遍機器學習的若幹算法,下面我們試着總結總結在拿到一個實際問題的時候,如果着手使用機器學習算法去解決問題,其中的一些注意點以及核心思路。主要包括以下内容:

拿到資料後怎麼了解資料(可視化)

選擇最貼切的機器學習算法

定位模型狀态(過/欠拟合)以及解決方法

大量極的資料的特征分析與可視化

各種損失函數(loss function)的優缺點及如何選擇

多說一句,這裡寫的這個小教程,主要是作為一個通用的建議和指導方案,你不一定要嚴格按照這個流程解決機器學習問題。

我們先使用scikit-learn的make_classification函數來生産一份分類資料,然後模拟一下拿到實際資料後我們需要做的事情。

機器學習算法一覽

我們生成了一份包含1000個分類資料樣本的資料集,每個樣本有20個數值特征。同時我們把資料存儲至pandas中的dataframe資料結構中。我們取前幾行的資料看一眼:

機器學習算法一覽

不幸的是,肉眼看資料,尤其是次元稍微高點的時候,很有可能看花了也看不出看不出任何線索。幸運的是,我們對于圖像的了解力,比數字好太多,而又有相當多的工具可以幫助我們『可視化』資料分布。

我們在處理任何資料相關的問題時,了解資料都是很有必要的,而可視化可以幫助我們更好地直覺了解資料的分布和特性
機器學習算法一覽
機器學習算法一覽

我們從散列圖和柱狀圖上可以看出,确實有些次元的特征相對其他次元,有更好的區分度,比如第11維和14維看起來很有區分度。這兩個次元上看,資料點是近似線性可分的。而12維和19維似乎呈現出了很高的負相關性。接下來我們用seanborn中的<code>corrplot</code>來計算計算各次元特征之間(以及最後的類别)的相關性。代碼和結果圖如下:

機器學習算法一覽
機器學習算法一覽

相關性圖很好地印證了我們之前的想法,可以看到第11維特征和第14維特征和類别有極強的相關性,同時它們倆之間也有極高的相關性。而第12維特征和第19維特征卻呈現出極強的負相關性。強相關的特征其實包含了一些備援的特征,而除掉上圖中顔色較深的特征,其餘特征包含的資訊量就沒有這麼大了,它們和最後的類别相關度不高,甚至各自之間也沒什麼先慣性。

插一句,這裡的次元隻有20,是以這個相關度計算并不費太大力氣,然而實際情形中,你完全有可能有遠高于這個數字的特征次元,同時樣本量也可能多很多,那種情形下我們可能要先做一些處理,再來實作可視化了。别着急,一會兒我們會講到。

我們隻有1000個資料樣本,是分類問題,同時是一個有監督學習,是以我們根據圖譜裡教的方法,使用<code>linearsvc</code>(support vector classification with linear kernel)試試。注意,<code>linearsvc</code>需要選擇正則化方法以緩解過拟合問題;我們這裡選擇使用最多的l2正則化,并把懲罰系數c設為10。我們改寫一下sklearn中的學習曲線繪制函數,畫出訓練集和交叉驗證集上的得分:

機器學習算法一覽
機器學習算法一覽
機器學習算法一覽

這幅圖上,我們發現随着樣本量的增加,訓練集上的得分有一定程度的下降,交叉驗證集上的得分有一定程度的上升,但總體說來,兩者之間有很大的差距,訓練集上的準确度遠高于交叉驗證集。這其實意味着我們的模型處于過拟合的狀态,也即模型太努力地刻畫訓練集,一不小心把很多噪聲的分布也拟合上了,導緻在新資料上的泛化能力變差了。

問題來了,過拟合咋辦?

針對過拟合,有幾種辦法可以處理:

增大樣本量

這個比較好了解吧,過拟合的主要原因是模型太努力地去記住訓練樣本的分布狀況,而加大樣本量,可以使得訓練集的分布更加具備普适性,噪聲對整體的影響下降。恩,我們提高點樣本量試試:

機器學習算法一覽
機器學習算法一覽

是不是發現問題好了很多?随着我們增大訓練樣本量,我們發現訓練集和交叉驗證集上的得分差距在減少,最後它們已經非常接近了。增大樣本量,最直接的方法當然是想辦法去采集相同場景下的新資料,如果實在做不到,也可以試試在已有資料的基礎上做一些人工的處理生成新資料(比如圖像識别中,我們可能可以對圖檔做鏡像變換、旋轉等等),當然,這樣做一定要謹慎,強烈建議想辦法采集真實資料。

減少特征的量(隻用我們覺得有效的特征)

比如在這個例子中,我們之前的資料可視化和分析的結果表明,第11和14維特征包含的資訊對識别類别非常有用,我們可以隻用它們。

機器學習算法一覽
機器學習算法一覽

從上圖上可以看出,過拟合問題也得到一定程度的緩解。不過我們這是自己觀察後,手動選出11和14維特征。那能不能自動進行特征組合和選擇呢,其實我們當然可以周遊特征的組合樣式,然後再進行特征選擇(前提依舊是這裡特征的次元不高,如果高的話,周遊所有的組合是一個非常非常非常耗時的過程!!):

機器學習算法一覽
機器學習算法一覽

如果你自己跑一下程式,會發現在我們自己手造的這份資料集上,這個特征篩選的過程超級順利,但依舊像我們之前提過的一樣,這是因為特征的次元不太高。

從另外一個角度看,我們之是以做特征選擇,是想降低模型的複雜度,而更不容易刻畫到噪聲資料的分布。從這個角度出發,我們還可以有(1)多項式你和模型中降低多項式次數

(2)神經網絡中減少神經網絡的層數和每層的結點數 (c)svm中增加rbf-kernel的bandwidth等方式來降低模型的複雜度。

話說回來,即使以上提到的辦法降低模型複雜度後,好像能在一定程度上緩解過拟合,但是我們一般還是不建議一遇到過拟合,就用這些方法處理,優先用下面的方法:

增強正則化作用(比如說這裡是減小linearsvc中的c參數)

正則化是我認為在不損失資訊的情況下,最有效的緩解過拟合現象的方法。

機器學習算法一覽
機器學習算法一覽

調整正則化系數後,發現确實過拟合現象有一定程度的緩解,但依舊是那個問題,我們現在的系數是自己敲定的,有沒有辦法可以自動選擇最佳的這個參數呢?可以。我們可以在交叉驗證集上做grid-search查找最好的正則化系數(對于大資料樣本,我們依舊需要考慮時間問題,這個過程可能會比較慢):

機器學習算法一覽

在500個點得到的結果是:{‘c’: 0.01}

使用新的c參數,我們再看看學習曲線:

機器學習算法一覽

對于特征選擇的部分,我打算多說幾句,我們剛才看過了用sklearn.feature_selection中的selectkbest來選擇特征的過程,也提到了在高維特征的情況下,這個過程可能會非常非常慢。那我們有别的辦法可以進行特征選擇嗎?比如說,我們的分類器自己能否甄别那些特征是對最後的結果有益的?這裡有個實際工作中用到的小技巧。

我們知道:

l2正則化,它對于最後的特征權重的影響是,盡量打散權重到每個特征次元上,不讓權重集中在某些次元上,出現權重特别高的特征。

而l1正則化,它對于最後的特征權重的影響是,讓特征獲得的權重稀疏化,也就是對結果影響不那麼大的特征,幹脆就拿不着權重。

那基于這個理論,我們可以把svc中的正則化替換成l1正則化,讓其自動甄别哪些特征應該留下權重。

機器學習算法一覽
機器學習算法一覽

好了,我們一起來看看最後特征獲得的權重:

機器學習算法一覽

得到結果:

機器學習算法一覽

你看,5 9 11 12 17 18這些次元的特征獲得了權重,而第11維權重最大,也說明了它影響程度最大。

我們再随機生成一份資料[1000*20]的資料(但是分布和之前有變化),重新使用linearsvc來做分類。

機器學習算法一覽
機器學習算法一覽

簡直爛出翔了有木有,二分類問題,我們做随機猜測,準确率都有0.5,這比随機猜測都高不了多少!!!怎麼辦?

不要盲目動手收集更多資料,或者調整正則化參數。我們從學習曲線上其實可以看出來,訓練集上的準确度和交叉驗證集上的準确度都很低,這其實就對應了我們說的『欠拟合』狀态。别急,我們回到我們的資料,還是可視化看看:

機器學習算法一覽
機器學習算法一覽

你發現什麼了,資料根本就沒辦法線性分割!!!,是以你再找更多的資料,或者調整正則化參數,都是無濟于事的!!!

那我們又怎麼解決欠拟合問題呢?通常有下面一些方法:

調整你的特征(找更有效的特征!!)

比如說我們觀察完現在的資料分布,然後我們先對資料做個映射:

機器學習算法一覽
機器學習算法一覽

卧槽,少年,這準确率,被吓尿了有木有啊!!!是以你看,選用的特征影響太大了,當然,我們這裡是人工模拟出來的資料,分布太明顯了,實際資料上,會比這個麻煩一些,但是在特征上面下的功夫還是很有回報的。

使用更複雜一點的模型(比如說用非線性的核函數)

我們對模型稍微調整了一下,用了一個複雜一些的非線性rbf kernel:

機器學習算法一覽
機器學習算法一覽

你看,效果依舊很贊。

我們在小樣本的toy dataset上,怎麼搗鼓都有好的方法。但是當資料量和特征樣本空間膨脹非常厲害時,很多東西就沒有那麼好使了,至少是一個很耗時的過程。舉個例子說,我們現在重新生成一份資料集,但是這次,我們生成更多的資料,更高的特征次元,而分類的類别也提高到5。

在上面提到的那樣一份資料上,我們用linearsvc可能就會有點慢了,我們注意到機器學習算法使用圖譜推薦我們使用<code>sgdclassifier</code>。其實本質上說,這個模型也是一個線性核函數的模型,不同的地方是,它使用了随機梯度下降做訓練,是以每次并沒有使用全部的樣本,收斂速度會快很多。再多提一點,<code>sgdclassifier</code>對于特征的幅度非常敏感,也就是說,我們在把資料灌給它之前,應該先對特征做幅度調整,當然,用sklearn的<code>standardscaler</code>可以很友善地完成這一點。

<code>standardscaler</code>每次隻使用一部分(mini-batch)做訓練,在這種情況下,我們使用交叉驗證(cross-validation)并不是很合适,我們會使用相對應的progressive validation:簡單解釋一下,estimator每次隻會拿下一個待訓練batch在本次做評估,然後訓練完之後,再在這個batch上做一次評估,看看是否有優化。

機器學習算法一覽

得到如下的結果:

機器學習算法一覽

大樣本資料的可視化是一個相對比較麻煩的事情,一般情況下我們都要用到降維的方法先處理特征。我們找一個例子來看看,可以怎麼做,比如我們資料集取經典的『手寫數字集』,首先找個方法看一眼這個圖檔資料集。

機器學習算法一覽
機器學習算法一覽

随機投射

我們先看看,把資料随機投射到兩個次元上的結果:

機器學習算法一覽

結果如下:

機器學習算法一覽

pca降維

在次元約減/降維領域有一個非常強大的算法叫做pca(principal component analysis,主成分分析),它能将原始的絕大多數資訊用次元遠低于原始次元的幾個主成分表示出來。pca在我們現在的資料集上效果還不錯,我們來看看用pca對原始特征降維至2維後,原始樣本在空間的分布狀況:

機器學習算法一覽

得到的結果如下:

機器學習算法一覽

我們可以看出,效果還不錯,不同的手寫數字在2維平面上,顯示出了區域集中性。即使它們之間有一定的重疊區域。

如果我們用一些非線性的變換來做降維操作,從原始的64維降到2維空間,效果更好,比如這裡我們用到一個技術叫做t-sne,sklearn的manifold對其進行了實作:

機器學習算法一覽
機器學習算法一覽

我們發現結果非常的驚人,似乎這個非線性變換降維過後,僅僅2維的特征,就可以将原始資料的不同類别,在平面上很好地劃分開。不過t-sne也有它的缺點,一般說來,相對于線性變換的降維,它需要更多的計算時間。也不太适合在大資料集上全集使用。

損失函數的選擇對于問題的解決和優化,非常重要。我們先來看一眼各種不同的損失函數:

機器學習算法一覽

得到結果圖像如下:

機器學習算法一覽

不同的損失函數有不同的優缺點:

0-1損失函數(zero-one loss)非常好了解,直接對應分類問題中判斷錯的個數。但是比較尴尬的是它是一個非凸函數,這意味着其實不是那麼實用。

hinge loss(svm中使用到的)的健壯性相對較高(對于異常點/噪聲不敏感)。但是它沒有那麼好的機率解釋。

log損失函數(log-loss)的結果能非常好地表征機率分布。是以在很多場景,尤其是多分類場景下,如果我們需要知道結果屬于每個類别的置信度,那這個損失函數很适合。缺點是它的健壯性沒有那麼強,相對hinge loss會對噪聲敏感一些。

多項式損失函數(exponential loss)(adaboost中用到的)對離群點/噪聲非常非常敏感。但是它的形式對于boosting算法簡單而有效。

感覺損失(perceptron loss)可以看做是hinge loss的一個變種。hinge loss對于判定邊界附近的點(正确端)懲罰力度很高。而perceptron loss,隻要樣本的判定類别結果是正确的,它就是滿意的,而不管其離判定邊界的距離。優點是比hinge loss簡單,缺點是因為不是max-margin boundary,是以得到模型的泛化能力沒有hinge loss強。

全文到此就結束了。先走馬觀花看了一遍機器學習的算法,然後給出了對應scikit-learn的『秘密武器』機器學習算法使用圖譜,緊接着從了解資料(可視化)、選擇機器學習算法、定位過/欠拟合及解決方法、大量極的資料可視化和損失函數優缺點與選擇等方面介紹了實際機器學習問題中的一些思路和方法。本文和文章機器學習系列(3)_邏輯回歸應用之kaggle泰坦尼克之災都提及了一些處理實際機器學習問題的思路和方法,有相似和互補之處,歡迎大家參照着看

原文釋出時間為:2016-01-12

本文來自雲栖社群合作夥伴“大資料文摘”,了解相關資訊可以關注“bigdatadigest”微信公衆号

繼續閱讀