探索圖片的真相–卷積神經網路

  • 2019 年 10 月 6 日
  • 筆記

今天給大家帶來的是卷積神經網路,聽上去是不是挺高大上的?它還有個更響亮的名字CNN,談到CNN應該好多同學都略知一二吧,CNN在做影像識別上有著很出色的效果,那我們今天對卷積神經網路一探究竟吧!

卷積神經網路,CNN(Convolutional Neural Network),屬於深度學習技術的一種演算法,主要是進行特徵學習,通過分層網路獲取分層次的特徵資訊去解決人工設計特徵的這個難題。

(TIPS:深度學習包含多種技術,CNN只是其中的一種,還包括:自動編碼器AutoEncoder,稀疏編碼Sparse Coding,限制玻爾茲曼機RBM,深信度網路Deep Belief Networks,多層回饋循環神經網路RNN)

卷積神經網路

關於卷積神經網路我們如何使用通俗易懂的語言來解釋它呢?

首先我們需要了解:它就是多層神經網路,善於解決影像識別問題。那如何去理解神經網路呢,我們可以簡單的想像一下那密密麻麻的漁網,網上的那些節組成的就是網路,節點和節點之間有線連接著,可以想像成每個神經元(節點)之間都產生連接。

那捲積神經網路為什麼對於影像識別分類有著更好的效果呢?

圖片數據對於機器來說是交大的數據,尤其是對於高清圖片,機器讀取和學習的時間也就越長,難度可以說指數級上升。但是卷積神經網路它可以將數據龐大的圖片識別問題去不斷降維(就是從影像中不斷去抽取細節特徵,從小的慢慢看),使得該影像最終能夠被訓練。

那麼卷積神經網路是怎樣工作的呢?

卷積神經網路是由三個層組成的,分別是:卷積層,池化層,全連接層。

卷積層與池化層聯合工作,形成卷積組,一層一層的去提取特徵,最終通過數個全連接層完成分類。

卷積層的原理其實就是局部視野的原理,有一張30*30的圖片,我每次只看3*3的大小(步長為3,不重複看),看100次全部看完,這就是卷積(看下圖去理解卷積)。池化層呢,就是降低維度,學術上又叫下取樣,就是從原圖片中進行取樣,對於一張720*1080的照片,池化層進行取樣,每次采30*30的大小,這就是池化了(看下圖去理解池化)。總的來說,CNN是通過卷積來區分特徵,並且通過卷積產生的權值共享和池化來降低網路參數的數量級,最後的工作就和普通神經網路的工作一樣了。

卷積神經網路在影像數據非常多的適合會有出乎意料的效果,但是數據集過少的時候往往效果不是很好,容易出現過擬合。

卷積

池化

LeNet介紹

我們來看看這一張圖,從原始圖片不斷提取,卷積。

先進入一個卷積層C1,由6個5×5的卷積核組成,卷積出28×28的影像,然後下取樣到14×14(S2),再進一個卷積層C3,由16個5×5的卷積核組成,之後再下取樣到5×5(S4)。我們可以看出,C3-0跟S2-0,1,2連接,C3-1跟S2-1,2,3連接,後面依次類推。最後,通過全連接層C5、F6得到10個輸出,對應10個數字的概率。

訓練

卷積神經網路的訓練分為兩個階段:

階段一:

正向傳播

A、從樣本集中取一個樣本(X,Yp),將X輸入網路;

B、計算相應的實際輸出Op。

在此階段,資訊從輸入層經過逐級的變換,傳送到輸出層。這個過程也是網路在完成訓練後正常運行時執行的過程。在此過程中,網路執行的是計算(實際上就是輸入與每層的權值矩陣相點乘,得到最後的輸出結果):

Op=Fn(…(F2(F1(XpW(1))W(2))…)W(n))

階段二:

反向傳播

A、算實際輸出Op與相應的理想輸出Yp的差;

B、按極小化誤差的方法反向傳播調整權矩陣。

下面我們看看在TensorFlow中我們是怎麼去做的吧!

前方程式碼過於簡單,及時帶好眼睛!!!

數據準備

教程的圖片從Cifar數據集中獲取,download_cifar.py從Keras自帶的Cifar數據集中獲取了部分Cifar數據集,並將其轉換為jpg圖片。

默認從Cifar數據集中選取了3類圖片,每類50張圖,分別是

0 => 飛機 1 => 汽車 2 => 鳥

導入相關庫

import os#影像讀取庫

from PIL import Image#矩陣運算庫

import numpy as np

import tensorflow as tf

配置資訊

設置了一些變數增加程式的靈活性。圖片文件存放在data_dir文件夾中,train表示當前執行是訓練還是測試,model-path約定了模型存放的路徑。

# 數據文件夾

data_dir = "data"

# 訓練還是測試

train = True

# 模型文件路徑

model_path = "model/image_model"

數據讀取

  • pillow讀取的影像像素值在0-255之間,需要歸一化。
  • 在讀取影像數據、Label資訊的同時,記錄影像的路徑,方便後期調試。

定義placeholder(容器)

定義卷積網路(Conv和Pooling部分)

定義全連接部分

定義損失函數和優化器

定義模型保存器/載入器

訓練階段執行

如果trian為True,進行訓練。訓練需要使用sess.run(tf.global_variables_initializer())初始化參數,訓練完成後,需要使用saver.save(sess, model_path)保存模型參數。

測試階段執行

如果train為False,進行測試,測試需要使用saver.restore(sess, model_path)讀取參數。

今天就到這裡了,其實細心的同學你們會發現程式碼大部分都是配置數據讀寫數據,真正花在訓練上的程式碼也不是很多,其實對於深度學習也就是這個意思,主要工作並不是敲程式碼,而是如何調參。TensorFlow在演算法的封裝上確實是做的很好的,我們可以直接拿過來用。大家也快去試試吧!

程式碼地址:

https://www.bytelang.com/o/s/c/uEOz1asEK6s=