keras集成學習一

文檔完整位置:https://docs.nn.knowledge-precipitation.site/ji-chu-zhi-shi/guo-ni-he/jichengxuexi-ensemble

集成學習的概念

當數據集有問題,或者網絡學習能力不足,或準確度不夠時,我們可以採取集成學習的方法,來提升性能。說得通俗一些,就是發揮團隊的智慧,根據團隊中不同背景、不同能力的成員的獨立意見,通過某種決策方法來解決一個問題。所以集成學習也稱爲多分類器系統(multi-classifier system)、基於委員會的學習(committee-based learning)等。

下是一個簡單的集成學習的示意圖。

在這裏插入圖片描述

圖中有兩個組件:

Individual Learner 個體學習器

如果所有的個體學習器都是同一類型的學習器,即同質模式,比如都用神經網路,稱爲“基學習器”(base learner),相應的學習算法稱爲“基學習算法”(base learning algorithm)。

在傳統的機器學習中,個體學習器可以是不同的,比如用決策樹、支持向量機等,此時稱爲異質模式。

Aggregator 結合模塊

個體學習器的輸出,通過一定的結合策略,在結合模塊中有機結合在一起,可以形成一個能力較強的學習器,所以有時稱爲強學習器,而相應地稱個體學習器爲弱學習器。

個體學習器之間是否存在依賴關係呢?這取決於產生個體學習器的方法:

  • Boosting系列算法,一系列的個體學習器需要一個個地串行生成,有前後依賴關係。
  • Bagging算法和隨機森林算法(Random Forest),個體學習器可以獨立或並行生成,沒有依賴關係。

我們只討論使用神經網絡的同質個體學習方法,和Bagging集成算法。由於神經網絡的複雜性,即使使用相同的網絡參數,由於初始化的不同或者訓練數據的不同,也可以得到差別很大的模型。

Bagging法集成學習的基本流程

下是Bagging集成學習的示意圖。
在這裏插入圖片描述

  1. 首先是數據集的使用,採用自助採樣法(Bootstrap Sampling)。假設原始數據集Training Set中有1000個樣本,我們從中隨機取一個樣本的拷貝放到Training Set-1中,此樣本不會從原始數據集中被刪除,原始數據集中還有1000個樣本,而不是999個,這樣下次再隨機取樣本時,此樣本還有可能被再次選到。如此重複m次(此例m=1000),我們可以生成Training Set-1。一共重複N次(此例N=9),可以得到N個數據集。
  2. 然後搭建一個神經網絡模型,可以參數相同。在N個數據集上,訓練出N個模型來。
  3. 最後再進入Aggregator。N值不能太小,否則無法提供差異化的模型,也不能太大而帶來訓練模型的時間花銷,一般來說取5到10就能滿足要求。

生成數據集

def GenerateDataSet(count=9):
    mdr = MnistImageDataReader(train_image_file, train_label_file, test_image_file, test_label_file, "vector")
    mdr.ReadLessData(1000)
    
    for i in range(count):
        X = np.zeros_like(mdr.XTrainRaw)
        Y = np.zeros_like(mdr.YTrainRaw)
        list = np.random.choice(1000,1000)
        k=0
        for j in list:
            X[k] = mdr.XTrainRaw[j]
            Y[k] = mdr.YTrainRaw[j]
            k = k+1
        # end for
        np.savez("level6_" + str(i)+".npz", data=X, label=Y)
    # end for

在上面的代碼中,我們假設只有1000個手寫數據樣本,用np.random.choice(1000,1000)函數來可重複地選取1000個數字,分別取出對應的圖像數據X和標籤數據Y,命名爲level6_N.npz,N=[1,9],保存到9個npz文件中。

假設數據集中有m個樣本,這樣的採樣方法,某個樣本在第一次被選擇的概率是1/m,那麼不被選擇的概率就是1-1/m,則選擇m次後,不被採樣到的概率是(11m)m(1-\frac{1}{m})^m,取極限值:

limm(11m)m1e=0.368 \lim_{m \rightarrow \infty} (1-\frac{1}{m})^m \simeq \frac{1}{e} = 0.368

即,對於一個新生成的訓練數據集來說,原始數據集中的樣本沒有被使用的概率爲36.8%。

訓練個體學習器神經網絡

這一步很簡單,依然用我們在Level0中的過擬合網絡,來訓練9個神經網絡。爲了體現“弱學習器”的概念,我們可以在訓練每個神經網絡時,只迭代10個epoch。

    nets = []
    net_count = 9
    for i in range(net_count):
        dataReader = LoadData(i)
        net = train(dataReader)
        nets.append(net)

上述代碼在一個9次的循環中,依次加載我們在前面生成的9個數據集,把訓練好的9個net保存到一個列表中,後面測試時使用。

集成方法選擇

平均法

在迴歸任務中,輸出爲一個數值,可以使用平均法來處理多個神經網絡的輸出值。下面公式中的hi(x)h_i(x)表示第i個神經網絡的輸出,H(x)H(x)表示集成後的輸出。

  • 簡單平均法:所有值加起來除以N。 H(x)=1Ni=1Nhi(x)H(x)=\frac{1}{N} \sum_{i=1}^N h_i(x)
  • 加權平均法:給每個輸出值一個人爲定義的權重。 H(x)=i=1Nwihi(x)H(x)=\sum_{i=1}^N w_i \cdot h_i(x)

權重值如何給出呢?假設第一個神經網絡的準確率爲80%,第二個爲85%,我們可以令:

w1=0.8 w1=0.8

w2=0.85 w2=0.85

這樣準確率高的網絡會得到較大的權重值。

投票法

對於分類任務,將會從類別標籤集合c1,c2,...,cn{c_1, c_2, ...,c_n}中預測出一個值,多個神經網絡可能會預測出不一樣的值,此時可以採樣投票法。

  • 絕對多數投票法(majority voting)

    當有半數以上的神經網路預測出同一個類別標籤時,我們可以認爲此預測有效。如果少於半數,則可以認爲預測無效。

    比如9個神經網絡,5個預測圖片上的數字爲7,則最終結果就是7。如果有4個神經網絡預測爲7,3個預測爲4,2個預測爲1,則認爲預測失敗。

  • 加權投票法(weighted voting)

    與加權平均法類似。

  • 相對多數投票法(plurality voting)

    即得票最多的標籤獲勝。如果有多個標籤獲得相同的票數,隨機選一個。

我們在代碼中使用了相對多數投票法,具體過程如下。

假設9個神經網絡對於同一張圖片的預測結果爲表16-5所示。

表16-5 9個神經網絡對某張圖片的預測結果

神經網絡ID 1 2 3 4 5 6 7 8 9
預測輸出 7 4 7 4 7 7 9 7 7

可以看到,在9個結果中,有6個結果預測爲7,2個預測爲4,1個預測爲9,我們選擇多數投票法,最終的預測結果爲7。

爲了驗證真實的準確率,我們可以用MNIST的測試集中的10000個樣本,來測試這9個模型,得到10000行上面表格中的數據,最後再統計最終的準確率。

此處代碼比較複雜,最關鍵的一行語句是:

ra[i] = np.argmax(np.bincount(predict_array[:,i]))

先使用np.bincount得到9個神經網絡的預測結果中,每個結果出現的次數,得到:

[0,1,0,0,2,0,0,6,0,1] [0,1,0,0,2,0,0,6,0,1]

其含義是:數字0出現了0次,數字1出現了1次,…數字4出現了2次,…,數字7出現了6次,等等。然後再用np.argmax([0,1,0,0,2,0,0,6,0,1])得到最大的數字6的下標,結果爲7。這樣就可以得到9個神經網絡的投票結果爲該圖片上的數字是7,因爲有6個神經網絡認爲是7,佔相對多數。

學習法

學習法,就是用另外一個神經網絡,通過訓練的方式,把9個神經網路的輸出結果作爲輸入,把圖片的真實數字作爲標籤,得到一個強學習器。

假設9個神經網絡的表現如表16-6所示。

表16-6 9個神經網絡對於原始數據集中的1000個樣本的預測結果

神經網絡ID 1 2 3 4 5 6 7 8 9 標籤值
預測輸出1 7 4 7 4 7 7 9 7 7 7
預測輸出2 4 4 7 4 7 4 9 4 7 4
預測輸出N 0 9 0 0 5 0 0 6 0 0
預測輸出1000 7 2 2 6 2 2 2 5 2 2

接下來我們可以建立一個兩層的神經網絡,輸入層爲9,用於接收9個神經網絡的預測輸出,隱層神經元數量不要大於16,輸出層爲10分類,標籤值爲上述表格中的最後一列。

scikit_learn中的ensemble

在這裏插入圖片描述

在keras中可以將模型轉換爲sklearn的迴歸或分類模型,傳入sklearn的函數中。

from keras.wrappers.scikit_learn import KerasRegressor, KerasClassifier


def build_model1():
    model = Sequential()
    model.add(Dense(128, activation='relu', input_shape=(13, )))
    model.add(Dense(64, activation='relu'))
    model.add(Dense(1, activation='linear'))
    model.compile(optimizer='adam',
                  loss='mean_squared_error')
    return model


def build_model2():
    model = Sequential()
    model.add(Dense(64, activation='relu', input_shape=(784, )))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(10, activation='softmax'))
    model.compile(optimizer='Adam',
                  loss='categorical_crossentropy',
                  metrics=['accuracy'])
    return model

model = KerasRegressor(build_fn=build_model1, epochs=100, batch_size=64)
model._estimator_type = "regressor"

model = KerasClassifier(build_fn=build_model2, epochs=2, batch_size=64)
model._estimator_type = "classifier"

運行結果

我們使用了相對多數投票法,其測試結果爲表16-7所示。

表16-7 9個神經網絡的預測準確率

神經網絡ID 準確率
1 0.8526
2 0.8482
3 0.8438
4 0.8327
5 0.8410
6 0.8452
7 0.8443
8 0.8397
9 0.8389

9個神經網絡的準確率如上表所示,最大的爲0.8526,最小的爲0.8327。用投票法得到的最後的準確率爲0.8751,得到了提升,達到了集成學習的目的。

從偏差-方差的角度看,Bagging主要起到降低方差的作用。在前面我們分析過,單個學習器的過擬合是高方差造成的,我們訓練多個這樣的學習器,隨機選擇的樣本數據如果分佈均勻的話,每個學習器在針對單個測試樣本時都會有高方差風險,從而產生泛化誤差。但是由於我們擁有9個神經網絡,採用集成法後,一定程度上緩解了高方差的現象。

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