卷積神經網絡 AlexNet

卷積神經網絡 AlexNet

1.介紹

LeNet 是最先推進深度學習領域發展的卷積神經網絡之一。這項由 Yann LeCun 完成的開創性工做自 1988 年以來屢次成功迭代以後被命名爲 LeNet5。AlexNet 是 Alex Krizhevsky 等人在 2012 年發表的《ImageNet Classification with Deep Convolutional Neural Networks》論文中提出的,並奪得了 2012 年 ImageNet LSVRC 的冠軍,引發了很大的轟動。AlexNet 能夠說是具備歷史意義的一個網絡結構,在此以前,深度學習已經沉寂了很長時間,自 2012 年 AlexNet 誕生以後,後面的 ImageNet 冠軍都是用卷積神經網絡(CNN)來作的,而且層次愈來愈深,使得CNN成爲在圖像識別分類的核心算法模型,帶來了深度學習的大爆發。本文將詳細講解 AlexNet 模型及其使用 Keras 實現過程。開始以前,先介紹一下卷積神經網絡。
html

2. 卷積神經網絡

2.1 卷積層

卷積是一種數學運算,它採用某種方式將一個函數「應用」到另外一個函數,結果能夠理解爲兩個函數的「混合體」。不過,這對檢測圖像中的目標有何幫助?事實證實,卷積很是擅長檢測圖像中的簡單結構,而後結合這些簡單特徵來構造更復雜的特徵。在卷積網絡中,會在一系列的層上發生此過程,每層對前一層的輸出執行一次卷積。卷積運算的目的是提取輸入的不一樣特徵,第一層卷積層可能只能提取一些低級的特徵如邊緣、線條和角等層級,更多層的網路能從低級特徵中迭代提取更復雜的特徵。
那麼,您會在計算機視覺中使用哪一種卷積呢?要理解這一點,首先了解圖像究竟是什麼。圖像是一種二階或三階字節數組,二階數組包含寬度和高度 2 個維度,三階數組有 3 個維度,包括寬度、高度和通道,因此灰階圖是二階的,而 RGB 圖是三階的(包含 3 個通道)。字節的值被簡單解釋爲整數值,描述了必須在相應像素上使用的特定通道數量。因此基本上講,在處理計算機視覺時,能夠將一個圖像想象爲一個 2D 數字數組(對於 RGB 或 RGBA 圖像,能夠將它們想象爲 3 個或 4 個 2D 數字數組的相互重疊)。
前端

微信圖片_20190619185025.png

圖1:卷積運算示意圖(左輸入,中過濾器,右輸出) 點我看計算演示
應該注意的是,步幅和過濾器大小是超參數,這意味着模型不會學習它們。因此您必須應用科學思惟來肯定這些數量中的哪些值最適合您的模型。對於卷積,您須要理解的最後一個概念是填充。若是您的圖像沒法在整數次內與過濾器擬合(將步幅考慮在內),那麼您必須填充圖像。可經過兩種方式實現此操做:VALID 填充和 SAME 填充。基本上講,VALID 填充丟棄了圖像邊緣的全部剩餘值。也就是說,若是過濾器爲 2 x 2,步幅爲 2,圖像的寬度爲 3,那麼 VALID 填充會忽略來自圖像的第三列值。SAME 填充向圖像邊緣添加值(一般爲 0)來增長它的維數,直到過濾器可以擬合整數次。這種填充一般以對稱方式進行的(也就是說,會嘗試在圖像的每一邊添加相同數量的列/行)。

2.2 激活層

激活層主要是激活函數的做用,那麼什麼是激活函數呢?在神經網絡中,當輸入激勵達到必定強度,神經元就會被激活,產生輸出信號。模擬這一細胞激活過程的函數,就叫激活函數。將神經元的輸出 f,做爲其輸入 x 的函數,對其建模的標準方法是用python

或者 sigmoid 函數
。就梯度降低的訓練時間而言,AlexNet 提出了比上面方式快 6 倍的 ReLu 函數
。ReLU 全稱爲修正線性單元(Rectified Linear Units)是一種針對元素的操做(應用於每一個像素),並將特徵映射中的全部負像素值替換爲零的非線性操做。其目的是在卷積神經網絡中引入非線性因素,由於在實際生活中咱們想要用神經網絡學習的數據大多數都是非線性的(卷積是一個線性運算 —— 按元素進行矩陣乘法和加法,因此咱們但願經過引入 ReLU 這樣的非線性函數來解決非線性問題)。
max.png

圖2: ReLU 函數(輸入小於0則輸出爲0,輸入大於0則輸出原值)

2.3 池化層

您會在卷積網絡中看到的另外一種重要的層是池化層。池化層具備多種形式:最大值,平均值,求和等。但最經常使用的是最大池化,其中輸入矩陣被拆分爲相同大小的分段,使用每一個分段中的最大值來填充輸出矩陣的相應元素。池化層能夠被認爲是由間隔爲 s 個像素的池單元網格組成,每一個池彙總了以池單元的位置爲中心的大小爲 z×z 的鄰域。若是咱們設置 s = z(池化窗口大小與步長相同),咱們得到在 CNN 中經常使用的傳統的局部合併。 若是咱們設置 s<z(每次移動的步長小於池化的窗口長度),咱們就得到重疊池化。在 AlexNet 中首次使用重疊池化來避免過擬合。
git

pooling.png

圖3:最大池化(左 16X16 大小分紅了 4 塊,黑子圈中是最大的數字)

2.4 全鏈接層

全鏈接層是一個傳統的多層感知器,它在輸出層使用 softmax 激活函數(也可使用其餘分類器,好比 SVM)。「徹底鏈接」這個術語意味着前一層中的每一個神經元都鏈接到下一層的每一個神經元。 這是一種普通的卷積網絡層,其中前一層的全部輸出被鏈接到下一層上的全部節點。卷積層轉換爲全鏈接層時,總神經元個數不變。 github

3. AlexNet 模型

3.1 模型介紹

CNN.png

圖4:AlexNet 模型( 5 卷積層+ 3 全鏈接層共 8 層神經網絡,使用 2GPU 故分上下兩部分)
AlexNet 模型包含 6 千萬個參數和 65 萬個神經元,包含 5 個卷積層,其中有幾層後面跟着最大池化(max-pooling)層,以及 3 個全鏈接層,最後還有一個 1000 路的 softmax 層。爲了加快訓練速度,AlexNet 使用了 Relu 非線性激活函數以及一種高效的基於 GPU 的卷積運算方法。爲了減小全鏈接層的過擬合,AlexNet 採用了最新的 「Dropout」防止過擬合方法,該方法被證實很是有效。

3.2 局部歸一化(Local Response Normalization,簡稱LRN)

在神經生物學有一個概念叫作「側抑制」(lateral inhibitio),指的是被激活的神經元抑制相鄰神經元。歸一化(normalization)的目的是「抑制」,局部歸一化就是借鑑了「側抑制」的思想來實現局部抑制,尤爲當使用 ReLU 時這種「側抑制」很管用,由於 ReLU 的響應結果是無界的(能夠很是大),因此須要歸一化。使用局部歸一化的方法有助於增長泛化能力。
算法

image.png

4. AlexNet 過擬合處理

4.1 數據擴充

減小圖像數據過擬合最簡單最經常使用的方法,是使用標籤-保留轉換,人爲地擴大數據集。AlexNet 模型使用兩種不一樣的形式,這兩種形式都容許轉換圖像用不多的計算量從原始圖像中產生,因此轉換圖像不須要存儲在磁盤上。數據擴充的第一種形式由生成圖像轉化和水平反射組成。數據擴充的第二種形式包含改變訓練圖像中 RGB 通道的強度。
數組

LRN.png

圖5:數據擴充三種方式

4.2 Dropout

對某一層神經元,Dropout 作的就是以 0.5 的機率將每一個隱層神經元的輸出設置爲零。以這種方式 「Dropped out」 的神經元既不用於前向傳播,也不參與反向傳播。因此每次提出一個輸入,該神經網絡就嘗試一個不一樣的結構,全部這些結構之間共享權重。由於神經元不能依賴於其餘特定神經元而存在,因此這種技術下降了神經元複雜的互適應關係。正因如此,要被迫學習更爲魯棒的特徵,這些特徵在結合其餘神經元的一些不一樣隨機子集時有用。若是沒有 Dropout,AlexNet 網絡會表現出大量的過擬合。
微信

Dropout.png

圖6:Dropout示意圖

5. 源碼解讀

5.1數據集和導入依賴庫

# (1) Importing dependency
import keras
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, Flatten, Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
import numpy as np
np.random.seed(1000)
# (2) Get Data
import tflearn.datasets.oxflower17 as oxflower17
x, y = oxflower17.load_data(one_hot=True)
# (3) Create a sequential model
model = Sequential()
複製代碼

AlexNet 模型創建在千分類問題上,其算力對計算機要求很高。這裏咱們爲了簡單復現,使用了 TensorFlow 的數據集 oxflower17 ,此數據集對花朵進行17 分類,每一個分類有 80 張照片。Keras 包含許多經常使用神經網絡構建塊的實現,例如層、目標、激活函數、優化器和一系列工具,能夠更輕鬆地處理圖像和文本數據。在 Keras 中有兩類主要的模型:Sequential 順序模型和使用函數式 API 的 Model 類模型。這裏使用 Sequential 模型。 網絡

5.3 第一次卷積+池化

# 1st Convolutional Layer
model.add(Conv2D(filters=96, input_shape=(224,224,3), kernel_size=(11,11), strides=(4,4), padding='valid'))
model.add(Activation('relu'))
# Pooling 
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation before passing it to the next layer
model.add(BatchNormalization())
複製代碼

image.png

卷積層 1 大小 224X224X3,卷積核大小 11X11X3,數量 48,步長爲 4。
關於卷積層的計算以下:

  • 輸入數據體尺寸爲
  • 4個超參數(模型不會學習優化):
    1. 濾波器數量
    2. 濾波器空間尺寸
    3. 卷積運算步長
    4. 零填充數量(SAME 填充)
  • 輸出數據體尺寸爲

這裏 W1=224,H1=224,D1=3,K=48,F=11,S=4,P=1.5。app

計算卷積層 2 有 W2=(224-11+3)/4+1=55,同理 H2=55,D2=K*2=96。

通過卷積運算後,輸出特徵圖像大小爲 55X55X96。
這裏使用了最大池化,步長爲 S=2,則 W=(55-3)/2+1=27。
再通過池化後,輸出特徵圖像大小爲 27X27X96。

5.4 第二次卷積+池化

# 2nd Convolutional Layer
model.add(Conv2D(filters=256, kernel_size=(11,11), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Pooling
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

卷積層 2 大小 55X55X96,卷積核大小 5X5,數量爲 128 個,步長爲 1。

同理,能夠計算卷積後獲得特徵圖像大小爲 27X27X256。
通過池化,輸出特徵圖像大小爲 13X13X256。**

5.5 第三次卷積

# 3rd Convolutional Layer
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

通過卷積後,特徵圖像大小爲 13X13X384。

5.6 第四次卷積

# 4th Convolutional Layer
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

通過卷積後,特徵圖像大小爲 13X13X284。

5.7 第五次卷積+池化

# 5th Convolutional Layer
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Pooling
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

通過卷積後,特徵圖像大小爲 13X13X256。

通過池化後,特徵圖像大小爲 6X6X256。

5.8 全鏈接層6

# Passing it to a dense layer
model.add(Flatten())
# 1st Dense Layer
model.add(Dense(4096, input_shape=(224*224*3,)))
model.add(Activation('relu'))
# Add Dropout to prevent overfitting
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

全鏈接層6大小爲 6X6X256,共 4096 個神經元,輸出 4096X1 的向量。

5.9 全鏈接層7

# 2nd Dense Layer
model.add(Dense(4096))
model.add(Activation('relu'))
# Add Dropout
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

全鏈接層7大小爲 4096X1,共 4096 個神經元,輸出 4096X1 的向量。

5.10 全鏈接層8

# 3rd Dense Layer
model.add(Dense(1000))
model.add(Activation('relu'))
# Add Dropout
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())
複製代碼

image.png

全鏈接層8輸入大小爲4096X1,共 4096 個神經元,輸出 1000X1 的向量。

5.11 輸出層及訓練

# Output Layer
model.add(Dense(17))
model.add(Activation('softmax'))
model.summary()
# (4) Compile 
model.compile(loss='categorical_crossentropy', optimizer='adam',metrics=['accuracy'])
# (5) Train
model.fit(x, y, batch_size=64, epochs=1, verbose=1, validation_split=0.2, shuffle=True)
複製代碼

最後在全鏈接層通過softmax激活函數後獲得結果。

image.png

在結果損失函數圖中,訓練集的損失值在迭代23次時達到最小。因爲數據量有限,測試集的損失值沒法降到理想位置。(橫座標是迭代次數,縱座標是損失函數的值)
image.png

能夠看出,在訓練集上能夠達到近90%的準確率。(橫座標是迭代次數,縱座標是準確率)
因爲數據集過小,測試集的準確率沒法達到理想的值。

6. 總結與展望

目前,您能夠在  Mo 平臺中找到基於 AlexNet 的項目 Flower,此項目對原文的千分類進行整合,最終作成花卉的17分類。您在學習的過程當中,遇到困難或者發現咱們的錯誤,能夠隨時聯繫咱們。
項目源碼地址:www.momodel.cn:8899/explore/5cf…

總結一下 AlexNet 的主要貢獻:

  1. 2 路 GPU 實現,加快了訓練速度
  2. Relu 非線性激活函數,減小訓練時間,加快訓練速度
  3. 重疊池化,提升精度,不容易產生過擬合
  4. 爲了減小過擬合,使用了數據擴充和 「Dropout」
  5. 使用局部響應歸一化,提升精度
  6. 5 個卷積層+ 3 個全鏈接層,結構性能良好

7. 參考

關於咱們

Mo(網址:momodel.cn)是一個支持 Python 的人工智能在線建模平臺,能幫助你快速開發、訓練並部署模型。


Mo 人工智能俱樂部 是由網站的研發與產品設計團隊發起、致力於下降人工智能開發與使用門檻的俱樂部。團隊具有大數據處理分析、可視化與數據建模經驗,已承擔多領域智能項目,具有從底層到前端的全線設計開發能力。主要研究方向爲大數據管理分析與人工智能技術,並以此來促進數據驅動的科學研究。

目前俱樂部每週六在杭州舉辦以機器學習爲主題的線下技術沙龍活動,不按期進行論文分享與學術交流。但願能匯聚來自各行各業對人工智能感興趣的朋友,不斷交流共同成長,推進人工智能民主化、應用普及化。

image.png
相關文章
相關標籤/搜索