機器學習 | 基礎通俗講解集成學習算法!


來源:Datawhale

本文約6000字,建議閱讀10+分鐘

本文以圖文的形式對模型算法中的集成學習,以及對集中學習在深度學習中的應用進行了詳細解讀。

標籤:機器學習

數據及背景

阿里天池-零基礎入門CV賽事:

https://tianchi.aliyun.com/competition/entrance/531795/introduction

集成學習

集成學習,即分類器集成,通過構建並結合多個學習器來完成學習任務。一般結構是:先產生一組“個體學習器”,再用某種策略將它們結合起來。結合策略主要有平均法、投票法和學習法等。集成學習(ensemble learning)通過構建並結合多個學習器來完成學習任務,有時也被稱爲多分類器系統(multi-classifier system)、基於委員會的學習(committee-based learning)。

集成學習是這樣一個過程,按照某種算法生成多個模型,如分類器或者稱爲專家,再將這些模型按照某種方法組合在一起來解決某個智能計算問題。集成學習主要用來提高模型(分類,預測,函數估計等)的性能,或者用來降低模型選擇不當的可能性。集成算法本身是一種監督學習算法,因爲它可以被訓練然後進行預測,組合的多個模型作爲整體代表一個假設(hypothesis)。

集成方法是將幾種機器學習技術組合成一個預測模型的元算法,以達到減小方差(bagging)、偏差(boosting) 或改進預測(stacking) 的效果。

分類器(Classifier)

分類器是數據挖掘中對樣本進行分類的方法的統稱,包含決策樹、邏輯迴歸、樸素貝葉斯、神經網絡等算法。分類是數據挖掘的一種非常重要的方法。分類的概念是在已有數據的基礎上學會一個分類函數或構造出一個分類模型(即分類器)。該函數或模型能夠把數據庫中的數據記錄映射到給定類別中的某一個,從而可以應用於數據預測。

分類器的構造和實施大體會經過以下幾個步驟:

  • 選定樣本(包含正樣本和負樣本),將所有樣本分成訓練樣本和測試樣本兩部分。

  • 在訓練樣本上執行分類器算法,生成分類模型。

  • 在測試樣本上執行分類模型,生成預測結果。

  • 根據預測結果,計算必要的評估指標,評估分類模型的性能。

1. 決策樹分類器

構造這個分類器不需要任何領域的知識,也不需要任何的參數設置。因此它特別適合於探測式的知識發現。此外,這個分類器還可以處理高維數據,而且採用的是類似於樹這種形式,也特別直觀和便於理解。因此,決策樹是許多商業規則歸納系統的基礎。

2. 樸素貝葉斯分類器

素貝葉斯分類器是假設數據樣本特徵完全獨立,以貝葉斯定理爲基礎的簡單概率分類器。

3. AdaBoost算法

AdaBoost算法的自適應在於前一個分類器產生的錯誤分類樣本會被用來訓練下一個分類器,從而提升分類準確率,但是對於噪聲樣本和異常樣本比較敏感。

4. 支持向量機

支持向量機是用過構建一個或者多個高維的超平面來將樣本數據進行劃分,超平面即爲樣本之間的分類邊界。

5. K近鄰算法

基於k近鄰的K個樣本作爲分析從而簡化計算提升效率,K近鄰算法分類器是基於距離計算的分類器。

集成學習方法

集成學習有許多集成模型,例如自助法、自助聚合(Bagging)、隨機森林、提升法(Boosting)、堆疊法(stacking)以及許多其它的基礎集成學習模型。

集成方法的思想是通過將這些個體學習器(個體學習器稱爲“基學習器”,基學習器也被稱爲弱學習器。)的偏置和/或方差結合起來,從而創建一個強學習器(或集成模型),從而獲得更好的性能。

我們可以用三種主要的旨在組合弱學習器的元算法:

  • 自助聚合(Bagging),該方法通常考慮的是同質弱學習器,相互獨立地並行學習這些弱學習器,並按照某種確定性的平均過程將它們組合起來。

  • 提升法(Boosting),該方法通常考慮的也是同質弱學習器。它以一種高度自適應的方法順序地學習這些弱學習器(每個基礎模型都依賴於前面的模型),並按照某種確定性的策略將它們組合起來。

  • 堆疊法(Stacking),該方法通常考慮的是異質弱學習器,並行地學習它們,並通過訓練一個 元模型 將它們組合起來,根據不同弱模型的預測結果輸出一個最終的預測結果。

非常粗略地說,我們可以說Bagging的重點在於獲得一個方差比其組成部分更小的集成模型,而Boosting和Stacking則將主要生成偏置比其組成部分更低的強模型(即使方差也可以被減小)。

1. 自助聚合(Bagging)

在並行化的方法中,我們單獨擬合不同的學習器,因此可以同時訓練它們。最著名的方法是自助聚合(Bagging),它的目標是生成比單個模型更棒的集成模型。Bagging的方法實現。

自助法:這種統計技術先隨機抽取出作爲替代的 B 個觀測值,然後根據一個規模爲 N 的初始數據集生成大小爲 B 的樣本(稱爲自助樣本)。

在某些假設條件下,這些樣本具有非常好的統計特性:在一級近似中,它們可以被視爲是直接從真實的底層(並且往往是未知的)數據分佈中抽取出來的,並且彼此之間相互獨立。因此,它們被認爲是真實數據分佈的代表性和獨立樣本(幾乎是獨立同分布的樣本)。

爲了使這種近似成立,必須驗證兩個方面的假設:

  • 初始數據集的大小N應該足夠大,以捕獲底層分佈的大部分複雜性。這樣,從數據集中抽樣就是從真實分佈中抽樣的良好近似(代表性);

  • 與自助樣本的大小B相比,數據集的規模N應該足夠大,這樣樣本之間就不會有太大的相關性(獨立性)。注意,接下來我可能還會提到自助樣本的這些特性(代表性和獨立性),但讀者應該始終牢記:這只是一種近似。

舉例而言,自助樣本通常用於評估統計估計量的方差或置信區間。根據定義,統計估計量是某些觀測值的函數。因此,隨機變量的方差是根據這些觀測值計算得到的。爲了評估這種估計量的方差,我們需要對從感興趣分佈中抽取出來的幾個獨立樣本進行估計。

在大多數情況下,相較於實際可用的數據量來說,考慮真正獨立的樣本所需要的數據量可能太大了。然而,我們可以使用自助法生成一些自助樣本,它們可被視爲最具代表性以及最具獨立性(幾乎是獨立同分布的樣本)的樣本。這些自助樣本使我們可以通過估計每個樣本的值,近似得到估計量的方差。

2. 提升法(Boosting)

在順序化的方法中,組合起來的不同弱模型之間不再相互獨立地擬合。其思想是迭代地擬合模型,使模型在給定步驟上的訓練依賴於之前的步驟上擬合的模型。提升法(Boosting)是這些方法中最著名的一種,它生成的集成模型通常比組成該模型的弱學習器偏置更小。

Boosting和Bagging的工作思路是一樣的:我們構建一系列模型,將它們聚合起來得到一個性能更好的強學習器。然而,與重點在於減小方差的Bagging不同,Boosting着眼於以一種適應性很強的方式順序擬合多個弱學習器:序列中每個模型在擬合的過程中,會更加重視那些序列中之前的模型處理的很糟糕的觀測數據。

直觀地說,每個模型都把注意力集中在目前最難擬合的觀測數據上。這樣一來,在這個過程的最後,我們就獲得了一個具有較低偏置的強學習器(我們會注意到,Boosting也有減小方差的效果)。和Bagging一樣,Boosting也可以用於迴歸和分類問題。由於其重點在於減小偏置,用於Boosting的基礎模型通常是那些低方差高偏置的模型。

例如,如果想要使用樹作爲基礎模型,我們將主要選擇只有少許幾層的較淺決策樹。而選擇低方差高偏置模型作爲Boosting弱學習器的另一個重要原因是:這些模型擬合的計算開銷較低(參數化時自由度較低)。實際上,由於擬合不同模型的計算無法並行處理(與Bagging不同),順序地擬合若干複雜模型會導致計算開銷變得非常高。

一旦選定了弱學習器,我們仍需要定義它們的擬合方式和聚合方式。介紹兩個重要的Boosting算法:自適應提升(adaboost)和梯度提升(gradient boosting)。

簡而言之,這兩種元算法在順序化的過程中創建和聚合弱學習器的方式存在差異。自適應提升算法會更新附加給每個訓練數據集中觀測數據的權重,而梯度提升算法則會更新這些觀測數據的值。這裏產生差異的主要原因是:兩種算法解決優化問題(尋找最佳模型——弱學習器的加權和)的方式不同。

2.1. 自適應adaboost

在自適應adaboost中,我們將集成模型定義爲L個弱學習器的加權和:

爲係數,爲弱學習器尋找這種最佳集成模型是一個困難的優化問題。因此,我們並沒打算一次性地解決該問題(找到給出最佳整體加法模型的所有係數和弱學習器),而是使用了一種更易於處理的迭代優化過程(即使它有可能導致我們得到次優解)。另外,我們將弱學習器逐個添加到當前的集成模型中,在每次迭代中尋找可能的最佳組合(係數、弱學習器)。換句話說,我們循環地將 定義如下:

其中,被挑選出來,使得是最適合訓練數據的模型,因此這是對 的最佳可能改進。我們可以進一步將其表示爲:

其中,是給定模型的擬合誤差,是損失/誤差函數。因此,我們並沒有在求和過程中對所有L個模型進行「全局優化」,而是通過「局部」優化來近似最優解並將弱學習器逐個添加到強模型中。

更特別的是,在考慮二分類問題時,我們可以將 adaboost 算法重新寫入以下過程:首先,它將更新數據集中觀測數據的權重,訓練一個新的弱學習器,該學習器重點關注當前集成模型誤分類的觀測數據。其次,它會根據一個表示該弱模型性能的更新系數,將弱學習器添加到加權和中:弱學習器的性能越好,它對強學習器的貢獻就越大。

因此,假設我們面對的是一個二分類問題:數據集中有N個觀測數據,我們想在給定一組弱模型的情況下使用adaboost算法。在算法的起始階段(序列中的第一個模型),所有的觀測數據都擁有相同的權重1/N。然後,我們將下面的步驟重複L次(作用於序列中的L個學習器):

  • 用當前觀測數據的權重擬合可能的最佳弱模型;

  • 計算更新系數的值,更新系數是弱學習器的某種標量化評估指標,它表示相對集成模型來說,該弱學習器的分量如何;

  • 通過添加新的弱學習器與其更新系數的乘積來更新強學習器計算新觀測數據的權重,該權重表示我們想在下一輪迭代中關注哪些觀測數據(聚和模型預測錯誤的觀測數據的權重增加,而正確預測的觀測數據的權重減小)。

重複這些步驟,我們順序地構建出L個模型,並將它們聚合成一個簡單的線性組合,然後由表示每個學習器性能的係數加權。注意,初始adaboost算法有一些變體,比如LogitBoost(分類)或L2Boost(迴歸),它們的差異主要取決於損失函數的選擇。

3. 堆疊法(Stacking)

堆疊法Stacking與Bagging和Boosting主要存在兩方面的差異。首先,堆疊法通常考慮的是異質弱學習器(不同的學習算法被組合在一起),而Bagging和Boosting主要考慮的是同質弱學習器。其次,stacking堆疊法學習用元模型組合基礎模型,而Bagging和Boosting則根據確定性算法組合弱學習器。

正如上文已經提到的,堆疊法的概念是學習幾個不同的弱學習器,並通過訓練一個元模型來組合它們,然後基於這些弱模型返回的多個預測結果輸出最終的預測結果。

因此,爲了構建Stacking模型,我們需要定義兩個東西:想要擬合的L個學習器以及組合它們的元模型。例如,對於分類問題來說,我們可以選擇KNN分類器、logistic迴歸和SVM作爲弱學習器,並決定學習神經網絡作爲元模型。然後,神經網絡將會把三個弱學習器的輸出作爲輸入,並返回基於該輸入的最終預測。所以,假設我們想要擬合由L個弱學習器組成的Stacking集成模型。我們必須遵循以下步驟:

  • 將訓練數據分爲兩組;

  • 選擇 L 個弱學習器,用它們擬合第一組數據;

  • 使 L 個學習器中的每個學習器對第二組數據中的觀測數據進行預測;

  • 在第二組數據上擬合元模型,使用弱學習器做出的預測作爲輸入。

在前面的步驟中,我們將數據集一分爲二,因爲對用於訓練弱學習器的數據的預測與元模型的訓練不相關。因此,將數據集分成兩部分的一個明顯缺點是,我們只有一半的數據用於訓練基礎模型,另一半數據用於訓練元模型。

爲了克服這種限制,我們可以使用某種k-折交叉訓練方法(類似於 k-折交叉驗證中的做法)。這樣所有的觀測數據都可以用來訓練元模型:對於任意的觀測數據,弱學習器的預測都是通過在k-1折數據(不包含已考慮的觀測數據)上訓練這些弱學習器的實例來完成的。換句話說,它會在k-1折數據上進行訓練,從而對剩下的一折數據進行預測。迭代地重複這個過程,就可以得到對任何一折觀測數據的預測結果。這樣一來,我們就可以爲數據集中的每個觀測數據生成相關的預測,然後使用所有這些預測結果訓練元模型。

十折交叉驗證

由於深度學習模型一般需要較長的訓練週期,如果硬件設備不允許建議選取留出法,如果需要追求精度可以使用交叉驗證的方法。

十折交叉驗證用來測試算法準確性。將數據集分成十份,輪流將其中九份作爲訓練數據,一份作爲測試數據,進行試驗。每次試驗都會得出相應的正確率(或差錯率)。十次的結果的正確率(或差錯率)的平均值作爲對算法精度的估計,一般還需要進行多次十折交叉驗證(例如十次十折交叉驗證),再求其均值,作爲對算法準確性的估計。

下面假設構建了十折交叉驗證,訓練得到十個CNN模型。

那麼在十個CNN模型可以使用如下方式進行集成:

  • 對預測的結果的概率值進行平均,然後解碼爲具體字符;

  • 對預測的字符進行投票,得到最終字符。


深度學習中的集成學習

此外在深度學習中本身還有一些集成學習思路的做法,值得借鑑學習:

  • 丟棄法Dropout

  • 測試集數據擴增TTA

  • Snapshot

1. 丟棄法Dropout

Dropout可以作爲訓練深度神經網絡的一種技巧。在每個訓練批次中,通過隨機讓一部分的節點停止工作。同時在預測的過程中讓所有的節點都起作用。

Dropout經常出現在在先有的CNN網絡中,可以有效的緩解模型過擬合的情況,也可以在預測時增加模型的精度。加入Dropout後的網絡結構如下:

# 定義模型
class SVHN_Model1(nn.Module):
    def __init__(self):
        super(SVHN_Model1, self).__init__()
        # CNN提取特徵模塊
        self.cnn = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=(3, 3), stride=(2, 2)),
            nn.ReLU(),
            nn.Dropout(0.25),
            nn.MaxPool2d(2),
            nn.Conv2d(16, 32, kernel_size=(3, 3), stride=(2, 2)),
            nn.ReLU(),
            nn.Dropout(0.25),
            nn.MaxPool2d(2),
        )
        #
        self.fc1 = nn.Linear(32*3*7, 11)
        self.fc2 = nn.Linear(32*3*7, 11)
        self.fc3 = nn.Linear(32*3*7, 11)
        self.fc4 = nn.Linear(32*3*7, 11)
        self.fc5 = nn.Linear(32*3*7, 11)
        self.fc6 = nn.Linear(32*3*7, 11)


    def forward(self, img):
        feat = self.cnn(img)
        feat = feat.view(feat.shape[0], -1)
        c1 = self.fc1(feat)
        c2 = self.fc2(feat)
        c3 = self.fc3(feat)
        c4 = self.fc4(feat)
        c5 = self.fc5(feat)
        c6 = self.fc6(feat)
        return c1, c2, c3, c4, c5, c6

2. 測試集數據擴增TTA

測試集數據擴增(Test Time Augmentation,簡稱TTA)也是常用的集成學習技巧,數據擴增不僅可以在訓練時候用,而且可以同樣在預測時候進行數據擴增,對同一個樣本預測三次,然後對三次結果進行平均。

def predict(test_loader, model, tta=10):   model.eval()   test_pred_tta = None   # TTA 次數   for _ in range(tta):       test_pred = []
       with torch.no_grad():           for i, (input, target) in enumerate(test_loader):               c0, c1, c2, c3, c4, c5 = model(data[0])               output = np.concatenate([c0.data.numpy(), c1.data.numpy(),                  c2.data.numpy(), c3.data.numpy(),                  c4.data.numpy(), c5.data.numpy()], axis=1)               test_pred.append(output)
       test_pred = np.vstack(test_pred)       if test_pred_tta is None:           test_pred_tta = test_pred       else:           test_pred_tta += test_pred
   return test_pred_tta

Snapshot

本章的開頭已經提到,假設我們訓練了10個CNN則可以將多個模型的預測結果進行平均。但是加入只訓練了一個CNN模型,如何做模型集成呢?

在論文Snapshot Ensembles中,作者提出使用cyclical learning rate進行訓練模型,並保存精度比較好的一些checkopint,最後將多個checkpoint進行模型集成。

由於在cyclical learning rate中學習率的變化有周期性變大和減少的行爲,因此CNN模型很有可能在跳出局部最優進入另一個局部最優。在Snapshot論文中作者通過使用表明,此種方法可以在一定程度上提高模型精度,但需要更長的訓練時間。


寫到最後

在不同的任務中可能會有不同的解決方案,不同思路的模型不僅可以互相借鑑,同時也可以修正最終的預測結果。

在本次賽題中,可以從以下幾個思路對預測結果進行後處理:

  • 統計圖片中每個位置字符出現的頻率,使用規則修正結果;

  • 單獨訓練一個字符長度預測模型,用來預測圖片中字符個數,並修正結果。

延伸閱讀:

  • 書籍:《深度實踐OCR:基於深度學習的文字識別》

  • 作者:劉樹春 阿里巴巴本地生活研究院算法專家,前復旦七牛雲聯合實驗室OCR算法負責人

編輯:黃繼彥

校對:林亦霖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章