天天看點

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

文章目錄

  • 第六章 圖像識别與卷積神經網絡
    • 6.1 圖像識别問題簡介及經典資料集
    • 6.2 卷積神經網絡簡介
    • 6.3 卷積神經網絡常用結構
      • 6.3.1 卷積層
      • 6.3.2 池化層

第六章 圖像識别與卷積神經網絡

通過MNIST資料集驗證了第四章介紹的神經網絡設計與優化的方法的實驗結果可以看出,神經網絡的結構會對神經網絡的準确率産生巨大的影響。

本章介紹一個非常常用的神經網絡結構——卷積神經網絡(Convolutional Neural Network,CNN)。

6.1 圖像識别問題簡介及經典資料集

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

CIFAR資料集就是一個影響力很大的圖像分類資料集。CIFAR資料集分為了CIFAR-10和CIFAR-100兩個問題,它們都是圖像詞典項目(Visual Dictionary)中800萬張圖檔的一個子集。

CIFAR-10問題收集了來自10個不同種類的60000張圖檔。如圖為示例圖檔及分類,像素為32×32

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

CIFAR官網提供了不同格式的CIFAR資料集下載下傳。

相比真實環境下的圖像識别問題,有兩個最大的問題。第一,現實生活中的圖像分辨率要遠高于32×32,而且圖像分辨率不會固定。第二,現實生活中的實體類别很多,而且一張圖檔中也不會隻出現一個種類的物體。

由斯坦福大學的李飛飛教授帶頭整理的ImageNet很大程度上解決了這兩個問題。

ImageNet是一個機遇WordNet的大型圖像資料庫。在ImageNet中,将近1500萬圖檔被關聯到了WordNet的大約20000個名詞同義詞集上。目前每一個與ImageNet相關的WordNet同義詞集都代表了現實世界中的一個實體,可以被認為是分類問題中的一個類别。ImageNet中的圖檔都是從網際網路上爬取下來的,并且通過亞馬遜的人工标注服務,将圖檔分類到WordNet 的同義詞集上。在ImageNet的圖檔中,一張圖檔中可能出現多個同義詞集所代表的實體。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

上圖為,物體識别任務,用矩形框(bounding box)框出實體,以用于更加精确的圖像識别。

ImageNet的官網中列出了曆屆ILSVRC競賽的題目和資料集。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

如圖,可以看出,基于卷積神經網絡的圖像識别算法可以遠超人類表現。

6.2 卷積神經網絡簡介

首先展示一下,全連接配接網絡與卷積神經網絡的結構上的差別。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

在全連接配接神經網絡中,每相鄰兩層之間的節點都有邊相連,于是一般會将每一層全連接配接層的節點組織成一列。

而對于卷積神經網絡,相鄰兩層之間隻有部分節點相連,為了展示每一層神經元的次元,一般會将每一層卷積層的節點組織成一個三維矩陣。

使用全連接配接網絡處理圖像的最大問題在于參數過多。對于MNIST資料集,每一張圖檔大小事28×28×1,28×28為圖像分辨率,1為色彩通道數。假設一層隐藏層節點數為500個,那麼一個全連接配接層的神經網絡參數有28×28×1×500+500=392500個。若是CIFAR資料集,32×32×32×500+500≈150萬個參數。參數過多不僅導緻計算效率低,也容易導緻過拟合問題。是以需要一個更加合理網絡結構來有效減少網絡參數個數。

下圖給出了一個更加具體的卷積神經網絡架構圖。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

一個卷積神經網絡主要由以下5中結構組成:

  • 1.輸入層。輸入一張圖像的像素矩陣,三維矩陣的長和寬代表圖像的像素大小,矩陣的深度代表圖像的色彩通道,灰階圖檔隻有一個通道,彩色圖檔有三個通道。
  • 2.卷積層。通過與過濾器進行卷積計算,提取某些圖像特征,得到抽象程度更高的特征,經過卷積層處理的節點矩陣會變得更深。
  • 3.池化層。池化層不會改變三維矩陣的深度,但會改變矩陣的長寬。赤化操作可以認為是将一張分辨率較高的圖檔轉化為分辨率較低的圖檔。
  • 4.全連接配接層。經過多輪卷積層和池化層處理之後,一般會由1到2個全連接配接層來給出最後的分類結果。經過幾輪卷積層和池化層處理之後,可以認為圖像中的資訊已經被抽象成了資訊含量更高的特征。可以把卷積、池化的過程看做自動圖像特征提取的過程,仍需要全連接配接層來完成分類任務。
  • 5.Softmax層。Softmax層主要用于分類問題。通過Softmax層,可以得到目前樣例屬于不同種類的機率分布情況,在實際應用中,也就是圖像分類得到的置信度。

6.3 卷積神經網絡常用結構

6.3.1 卷積層

TensorFlow文檔中将圖中結構稱為過濾器(filter),我更習慣稱之為卷積核(kernel)。

過濾器可以将目前層神經網絡上的一個子節點矩陣轉化為下層神經網絡上的一個機關節點矩陣。機關節點矩陣指的是長和寬都為1,但深度不限的節點矩陣。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

過濾器的長度和寬都是人工指定的,這個節點矩陣的尺寸也被稱之為過濾器的尺寸,常用的過濾器尺寸有3×3或5×5。因為過濾器的矩陣深度和目前層神經網絡矩陣的深度是一緻的,是以無需指定過濾器矩陣的深度。

另外一個需要指定的參數是處理得到的機關節點矩陣的深度,也就是過濾器的個數。由于一次卷積計算得到的是一個數值,是以過濾器的個數,決定了處理後的矩陣深度。

TensorFlow對卷積網絡的解釋太複雜了…我還是寫的通俗一點。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

請忽略g(0)的意義,左上為輸入的圖像矩陣的第一個要進行卷積計算的子矩陣,a[::0]、a[::1]、a[::2]為三個顔色通道上的子矩陣。對應的卷積核也有三個通道,a[::0]與w[::0]進行卷積計算,也就是對位相乘然後加和,三個通道的卷積計算結束後,再加上一個偏置量1就完成了一次卷積計算過程。

右側是整個計算的過程,此次卷積計算的結果為-3。

如圖一個卷積核同圖像子矩陣進行卷積計算隻得到了一個數字,那麼一個卷積核同圖像矩陣進行卷積計算得到的就是一個新的深度為1的矩陣。多個卷積核計算的結果會堆疊成新的矩陣,每多一個卷積核,得到的矩陣的深度就加一。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

如圖,根據邊框的顔色,可以看出卷積層前向傳播的過程。上圖步長為1,即每次移動一格。

為了避免尺寸的變化,可以在目前層矩陣的邊界加上全0填充(zero-padding)。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

加入全0填充後,就可以保證卷積計算前後,矩陣尺寸不發生變化了。

還可以通過設定卷積核移動的步長來調整結果矩陣的大小。上兩圖步長均為1,下圖展示了當移動步長為2時,卷積層的前向傳播過程。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

顯然步長為2時,結果矩陣的長和寬隻有原來的一半。

下圖給出了使用了全0填充、步長為2的卷積層前向傳播的計算流程。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡

ReLU(0×1+0×(-1)+0×0+1×2+1)=ReLU(3)=3

以下代碼實作了卷積層的前向傳播過程。

# -*- coding: utf-8 -*-
# @Time    : 2019/3/20 20:36
# @Author  : Chord

import tensorflow as tf;
# 通過tf.get_variable的方式建立卷積核的權重變量和偏置項變量。上面介紹了卷積層
# 的參數個數隻和卷積核尺寸、個數以及目前層節點矩陣的深度油管,是以這裡聲明的參
# 數變量是一個四維矩陣,前面兩個次元帶包了卷積核的尺寸,第三個尺寸表示目前層的
# 深度,第四個次元表示卷積核的個數
filter_weight = tf.get_variable(
    'weights', [5, 5, 3, 16],
    initializer=tf.truncated_normal_initializer(0.1)
)
# 和卷積層的權重類似,目前層矩陣上不同位置的偏置項也是共享的,是以總共有下一層
# 深度個不同的偏置項,或者每個卷積核有一個偏置項。
biases = tf.get_variable(
    'biases', [16], initializer=tf.constant_initializer(0.1)
)

# tf.nn.conv2d提供了一個非常友善的函數來實作卷積層的前向傳播算法。這個函數的第
# 一個輸入為目前層的節點矩陣。注意這個矩陣是一個四維矩陣,後面三個次元對應一個
# 節點矩陣,第一維對應一個輸入batch。比如在輸入層,input[0,:,:,:]表示第一張圖檔,
# input[1,:,:,:]表示第二張圖檔。tf.nn.conv2d第二個參數提供了卷積層的權重,第三
# 個參數為不同次元上的步長。雖然第三個參數提供的是一個長度為4的數組,但是第一維
# 和最後一維的數字要求一定是1。這是因為卷積層的步長支隊矩陣的長和寬有效。最後一
# 個參數是填充(padding)方法,TensorFlow中聽過SAME或是VALID兩種選擇。啟動SAME
# 表示全0填充,VALID表示不添加
conv = tf.nn.conv2d(
    input, filter_weight, strides=[1, 1, 1, 1], padding='SAME'
)

# tf.nn.bias_add提供了一個友善的函數給每一個節點加上偏置項。注意這裡不能直接使用
# 加法,因為矩陣上不同位置上的幾點都需要加上那個同樣的偏置項。
bias = tf.nn.bias_add(conv, biases)
# 将計算結果通過ReLU激活函數完成去線性化
actived_conv = tf.nn.relu(bias)
           

6.3.2 池化層

池化層的前向傳播過程也是通過移動一個滑塊結構完成的。池化層一般分為兩種。

第一種,使用最大值操作的池化層被稱為最大池化層(max pooling)。第二張,使用平均值操作的池化層被稱為平均池化層(average pooling)。

池化層的過濾器同樣需要人工設定尺寸、步長、是否全0填充等。設定的意義與卷積層相同,唯一的差別在于卷積核的卷積計算橫跨深度,而池化層的過濾器每次隻影響一個深度上的節點。

下圖展示了在輸入子矩陣a的第0個通道、第1個通道分别進行最大池化的過程。

學習《TensorFlow實戰Google深度學習架構》(八) 卷積神經網絡簡介第六章 圖像識别與卷積神經網絡
# tf.nn.max_pool實作了最大池化層的前向傳播過程,它的參數和tf.nn.conv2d函數類似
# ksize提供了過濾器的尺寸,strides提供了步長資訊,padding提供了是否使用全0填充
pool = tf.nn.max_pool(actived_conv, ksize=[1, 3, 3, 1],
                      strides=[1, 2, 2, 1], padding='SAME')
                      # 3×3的過濾器,步長為2                
           

繼續閱讀