在訓練了 50 個 epoch 之後,本文作者驚訝地發現模型什麼都沒學到,於是開始深挖背後的問題,並最終從愷明大神論文中得到的知識解決了問題。

選自Medium,作者:Nathan Hubens,機器之心編譯,參與:Nurhachu Null、張倩。

上個星期我做了一些實驗,用了在 CIFAR10 資料集上訓練的 VGG16。我需要從零開始訓練模型,所以沒有使用在 ImageNet 上預訓練的版本。

我開始了 50 個 epoch 的訓練,然後去喝了個咖啡,回來就看到了這些學習曲線:

為何Keras中的CNN是有問題的,如何修復它們?

模型什麼都沒學到!

我見過網路收斂得極其緩慢、振盪、過擬合、發散,但這是我第一次發現這種行為——模型根本就沒有起任何作用。

因此我就深挖了一下,看看究竟發生了什麼。

實驗

這是我建立模型的方法。它遵循了 VGG16 的原始結構,但是,大多數全連線層被移除了,所以只留下了相當多的卷積層。

為何Keras中的CNN是有問題的,如何修復它們?

現在讓我們瞭解一下是什麼導致了我在文章開頭展示的訓練曲線。

學習模型過程中出現錯誤時,檢查一下梯度的表現通常是一個好主意。我們可以使用下面的方法得到每層梯度的平均值和標準差:

為何Keras中的CNN是有問題的,如何修復它們?

然後將它們畫出來,我們就得到了以下內容:

為何Keras中的CNN是有問題的,如何修復它們?

使用 Glorot 函式初始化的 VGG16 梯度的統計值

呀。。。 我的模型中根本就沒有梯度,或許應該檢查一下啟用值是如何逐層變化的。我們可以試用下面的方法得到啟用值的平均值和標準差:

為何Keras中的CNN是有問題的,如何修復它們?

然後將它們畫出來:

為何Keras中的CNN是有問題的,如何修復它們?

使用 Glorot 函式進行初始化的 VGG16 模型的啟用值

這就是問題所在!

提醒一下,每個卷積層的梯度是透過以下公式計算的:

為何Keras中的CNN是有問題的,如何修復它們?

其中Δx 和Δy 用來表示梯度∂L/∂x 和∂L/∂y。梯度是透過反向傳播演算法和鏈式法則計算的,這意味著我們是從最後一層開始,反向傳遞到較淺的層。但當最後一層的啟用值接近零時會發生什麼呢?這正是我們面臨的情況,梯度到處都是零,所以不能反向傳播,導致網路什麼都學不到。

由於我的網路是相當簡約的:沒有批歸一化,沒有 Dropout,沒有資料增強,所以我猜問題可能來源於比較糟糕的初始化,因此我拜讀了何愷明的論文——《Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification》

論文連結:

https://

arxiv。org/pdf/1502。0185

2。pdf

下面簡要描述一下論文內容。

初始化方法

初始化始終是深度學習研究中的一個重要領域,尤其是結構和非線性經常變化的時候。實際上一個好的初始化是我們能夠訓練深度神經網路的原因。

以下是何愷明論文中的關鍵思想,他們展示了初始化應該具備的條件,以便使用 ReLU 啟用函式正確初始化 CNN。這裡會需要一些數學知識,但是不必擔心,你只需抓住整體思路。

我們將一個卷積層 l 的輸出寫成下面的形式:

為何Keras中的CNN是有問題的,如何修復它們?

接下來,如果偏置值被初始化為 0,再假設權重 w 和元素 x 相互獨立並且共享相同的分佈,我們就得到了:

為何Keras中的CNN是有問題的,如何修復它們?

其中 n 是一層的權重數目(例如 n=k²c)。透過獨立變數的乘積的方差公式:

為何Keras中的CNN是有問題的,如何修復它們?

它變成了:

為何Keras中的CNN是有問題的,如何修復它們?

然後,如果我們讓權重 w 的均值為 0,就會得到:

為何Keras中的CNN是有問題的,如何修復它們?

透過 König-Huygens 性質:

為何Keras中的CNN是有問題的,如何修復它們?

最終得到:

為何Keras中的CNN是有問題的,如何修復它們?

然而,由於我們使用的是 ReLU 啟用函式,所以就有了:

為何Keras中的CNN是有問題的,如何修復它們?

因此:

為何Keras中的CNN是有問題的,如何修復它們?

這就是一個單獨卷積層的輸出的方差,到那時如果我們想考慮所有層的情況,就必須將它們乘起來,這就得到了:

為何Keras中的CNN是有問題的,如何修復它們?

由於我們做了乘積,所以現在很容易看到如果每一層的方差不接近於 1,網路就會快速衰減。實際上,如果它比 1 小,就會快速地朝著零消散,如果比 1 大,啟用的值就會急劇增長,甚至變成一個你的計算機都無法表示的數字(NaN)。因此,為了擁有表現良好的 ReLU CNN,下面的問題必須被重視:

為何Keras中的CNN是有問題的,如何修復它們?

作者比較了使用標準初始化(Xavier/Glorot)[2] 和使用它們自己的解初始化深度 CNN 時的情況:

為何Keras中的CNN是有問題的,如何修復它們?

在一個 22 層的 ReLU CNN 上使用 Glorot(藍色)初始化和 Kaiming 的初始化方法進行訓練時的對比。使用 Glorot 初始化的模型沒有學到任何東西。

這幅圖是不是很熟悉?這就是我在文章開始向你們展示的圖形!使用 Xavier/Glorot 初始化訓練的網路沒有學到任何東西。

現在猜一下 Keras 中預設的初始化是哪一種?

沒錯!在 Keras 中,卷積層預設是以 Glorot Uniform 分佈進行初始化的:

為何Keras中的CNN是有問題的,如何修復它們?

所以如果我們將初始化方法改成 Kaiming Uniform 分佈會怎麼樣呢?

使用 Kaiming 的初始化方法

現在來建立我們的 VGG16 模型,但是這次將初始化改成 he_uniform。

在訓練模型之前,讓我們來檢查一下啟用值和梯度。

為何Keras中的CNN是有問題的,如何修復它們?

所以現在,使用 Kaiming 的初始化方法時,我們的啟用擁有 0。5 左右的均值,以及 0。8 左右的標準差。

為何Keras中的CNN是有問題的,如何修復它們?

可以看到,現在我們有一些梯度,如果希望模型能夠學到一些東西,這種梯度就是一種好現象了。

現在,如果我們訓練一個新的模型,就會得到下面的學習曲線:

為何Keras中的CNN是有問題的,如何修復它們?

我們可能需要增加一些正則化,但是現在,哈哈,已經比之前好很多了,不是嗎?

結論

在這篇文章中,我們證明,初始化是模型中特別重要的一件事情,這一點你可能經常忽略。此外,文章還證明,即便像 Keras 這種卓越的庫中的預設設定,也不能想當然拿來就用。

參考文獻和擴充套件閱讀:

[1]: Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification:

https://

arxiv。org/pdf/1502。0185

2。pdf

[2]: Understanding the difficulty of training deep feedforward neural networks:

http://

proceedings。mlr。press/v

9/glorot10a/glorot10a。pdf

[3]: 吳恩達課程:

https://www。

youtube。com/watch?

v=s2coXdufOzE

原文地址:

https://

towardsdatascience。com/

why-default-cnn-are-broken-in-keras-and-how-to-fix-them-ce295e5e5f2