[Python人工智能] 十八.Keras搭建卷積神經網絡及CNN原理詳解
代碼-:https://github.com/eastmountyxz/AI-for-TensorFlow
代碼-:https://github.com/eastmountyxz/AI-for-Keras
文章目錄
一.卷積神經網絡原理
1.什么是CNN
2.CNN原理
二.Keras實現CNN
1.代碼實現
2.完整代碼
3.運行結果
三.總結
華為云社區前文賞析:
[Python人工智能] 一.TensorFlow2.0環境搭建及神經網絡入門
[Python人工智能] 二.TensorFlow基礎及一元直線預測案例
[Python人工智能] 三.TensorFlow基礎之Session、變量、傳入值和激勵函數
[Python人工智能] 四.TensorFlow創建回歸神經網絡及Optimizer優化器
[Python人工智能] 五.Tensorboard可視化基本用法及繪制整個神經網絡
[Python人工智能] 六.TensorFlow實現分類學習及MNIST手寫體識別案例
[Python人工智能] 七.什么是過擬合及dropout解決神經網絡中的過擬合問題
[Python人工智能] 八.卷積神經網絡CNN原理詳解及TensorFlow編寫CNN
[Python人工智能] 九.gensim詞向量Word2Vec安裝及《慶余年》中文短文本相似度計算
[Python人工智能] 十.Tensorflow+Opencv實現CNN自定義圖像分類及與KNN圖像分類對比
[Python人工智能] 十一.Tensorflow如何保存神經網絡參數
[Python人工智能] 十二.循環神經網絡RNN和LSTM原理詳解及TensorFlow編寫RNN分類案例
[Python人工智能] 十三.如何評價神經網絡、loss曲線圖繪制、圖像分類案例的F值計算
[Python人工智能] 十四.循環神經網絡LSTM RNN回歸案例之sin曲線預測 丨【百變AI秀】
[Python人工智能] 十五.無監督學習Autoencoder原理及聚類可視化案例詳解
[Python人工智能] 十六.Keras環境搭建、入門基礎及回歸神經網絡案例
[Python人工智能] 十七.Keras搭建分類神經網絡及MNIST數字圖像案例分析
[Python人工智能] 十八.Keras搭建卷積神經網絡及CNN原理詳解
一.卷積神經網絡原理
1.什么是CNN
一般的神經網絡在理解圖片信息的時候還是有不足之處,這時卷積神經網絡就成為了計算機處理圖片的助推器。卷積神經網絡的英文是Convolutional Neural Network,簡稱CNN。它通常應用于圖像識別和語音識等領域,并能給出更優秀的結果,也可以應用于視頻分析、機器翻譯、自然語言處理、藥物發現等領域。著名的阿爾法狗讓計算機看懂圍棋就是基于卷積神經網絡的。
神經網絡是由很多神經層組成,每一層神經層中存在很多神經元,這些神經元是識別事物的關鍵,當輸入是圖片時,其實就是一堆數字。
首先,卷積是什么意思呢?卷積是指不在對每個像素做處理,而是對圖片區域進行處理,這種做法加強了圖片的連續性,看到的是一個圖形而不是一個點,也加深了神經網絡對圖片的理解。
卷積神經網絡批量過濾器,持續不斷在圖片上滾動搜集信息,每一次搜索都是一小塊信息,整理這一小塊信息之后得到邊緣信息。比如第一次得出眼睛鼻子輪廓等,再經過一次過濾,將臉部信息總結出來,再將這些信息放到全神經網絡中進行訓練,反復掃描最終得出的分類結果。如下圖所示,貓的一張照片需要轉換為數學的形式,這里采用長寬高存儲,其中黑白照片的高度為1,彩色照片的高度為3(RGB)。
過濾器搜集這些信息,將得到一個更小的圖片,再經過壓縮增高信息嵌入到普通神經層上,最終得到分類的結果,這個過程即是卷積。Convnets是一種在空間上共享參數的神經網絡,如下圖所示,它將一張RGB圖片進行壓縮增高,得到一個很長的結果。
近幾年神經網絡飛速發展,其中一個很重要的原因就是CNN卷積神經網絡的提出,這也是計算機視覺處理的飛躍提升。關于TensorFlow中的CNN,Google公司也出了一個非常精彩的視頻教程,也推薦大家去學習。
Google官方卷積神經網絡介紹視頻 - 優達學城
2.CNN原理
本文主要講解如何去應用CNN,下面我們先簡單看看CNN是如何處理信息的。這里參考Google官方視頻介紹,強烈推薦大家學習。
假設你有一張小貓咪的照片,如下圖所示,它可以被表示為一個博餅,它有寬度(width)和高度(height),并且由于天然存在紅綠藍三色,它還擁有RGB厚度(depth),此時你的輸入深度為3。
假設我們現在拿出圖片的一小塊,運行一個具有K個輸出的小神經網絡,像圖中一樣把輸出表示為垂直的一小列。
在不改變權重的情況下,通過小神經網絡滑動掃遍整個圖片,就像我們拿著刷子刷墻一樣水平垂直的滑動。
此時,輸出端畫出了另一幅圖像,如下圖中紅色區域所示。它與之前的寬度和高度不同,更重要的是它跟之前的深度不同,而不是僅僅只有紅綠藍,現在你得到了K個顏色通道,這種操作稱為——卷積。
如果你的塊大小是整張圖片,那它跟普通的神經網絡層沒有任何區別,正是由于我們使用了小塊,我們有很多小塊在空間中共享較少的權重。卷積不在對每個像素做處理,而是對圖片區域進行處理,這種做法加強了圖片的連續性,也加深了神經網絡對圖片的理解。
一個卷積網絡是組成深度網絡的基礎,我們將使用數層卷積而不是數層的矩陣相乘。如下圖所示,讓它形成金字塔形狀,金字塔底是一個非常大而淺的圖片,僅包括紅綠藍,通過卷積操作逐漸擠壓空間的維度,同時不斷增加深度,使深度信息基本上可以表示出復雜的語義。同時,你可以在金字塔的頂端實現一個分類器,所有空間信息都被壓縮成一個標識,只有把圖片映射到不同類的信息保留,這就是CNN的總體思想。
上圖的具體流程如下:
首先,這是有一張彩色圖片,它包括RGB三原色分量,圖像的長和寬為256*256,三個層面分別對應紅(R)、綠(G)、藍(B)三個圖層,也可以看作像素點的厚度。
其次,CNN將圖片的長度和寬度進行壓縮,變成12812816的方塊,壓縮的方法是把圖片的長度和寬度壓小,從而增高厚度。
再次,繼續壓縮至646464,直至3232256,此時它變成了一個很厚的長條方塊,我們這里稱之為分類器Classifier。該分類器能夠將我們的分類結果進行預測,MNIST手寫體數據集預測結果是10個數字,比如[0,0,0,1,0,0,0,0,0,0]表示預測的結果是數字3,Classifier在這里就相當于這10個序列。
最后,CNN通過不斷壓縮圖片的長度和寬度,增加厚度,最終會變成了一個很厚的分類器,從而進行分類預測。
如果你想實現它,必須還要正確實現很多細節。此時,你已經接觸到了塊和深度的概念,塊(PATCH)有時也叫做核(KERNEL),如下圖所示,你堆棧的每個薄餅都被叫做特征圖(Feature Map),這里把三個特性映射到K個特征圖中,PATCH/KERNEL的功能是從圖片中抽離一小部分進行分析,每次抽離的小部分都會變成一個長度、一個寬度、K個厚度的數列。
另一個你需要知道的概念是——步幅(STRIDE)。它是當你移動濾波器或抽離時平移的像素的數量,每一次跨多少步去抽離圖片中的像素點。
如果步幅STRIDE等于1,表示每跨1個像素點抽離一次,得到的尺寸基本上和輸入相同。
如果步幅STRIDE等于2,表示每次跨2個像素點抽離,意味著變為一半的尺寸。它收集到的信息就會被縮減,圖片的長度和寬度被壓縮了,壓縮合并成更小的一塊立方體。
壓縮完之后再合并成一個立方體,它就是更小的一塊立方體,包含了圖片中的所有信息。
抽離圖片信息的方式稱為PADDING(填充),一般分為兩種:
VALID PADDING:?抽出來這層比原先那層圖片寬和長裁剪了一點,抽取的內容全部是圖片內的。
SAME PADDING:?抽離出的那層與之前的圖片一樣的長和寬,抽取的內容部分再圖片外,圖片外的值用0來填充。
研究發現,卷積過程會丟失一些信息,比如現在想跨2步去抽離原始圖片的重要信息,形成長寬更小的圖片,該過程中可能會丟失重要的圖片信息。為了解決這個問題,通過POOLING(持化)可以避免。其方法是:卷積時不再壓縮長寬,盡量保證更多信息,壓縮工作交給POOLING。經過圖片到卷積,持化處理卷積信息,再卷積再持化,將結果傳入兩層全連接神經層,最終通過分類器識別貓或狗。
總結:整個CNN從下往上依次經歷“圖片->卷積->持化->卷積->持化->結果傳入兩層全連接神經層->分類器”的過程,最終實現一個CNN的分類處理。
IMAGE 圖片
CONVOLUTION 圖層
MAX POOLING 更好地保存原圖片的信息
CONVOLUTION 圖層
MAX POOLING 更好地保存原圖片的信息
FULLY CONNECTED 神經網絡隱藏層
FULLY CONNECTED 神經網絡隱藏層
CLASSIFIER 分類器
寫到這里,CNN的基本原理講解完畢,希望大家對CNN有一個初步的理解。同時建議大家處理神經網絡時,先用一般的神經網絡去訓練它,如果得到的結果非常好,就沒必要去使用CNN,因為CNN結構比較復雜。
二.Keras實現CNN
接著我們講解如何在Keras代碼中編寫CNN。
1.代碼實現
第一步,打開Anaconda,然后選擇已經搭建好的“tensorflow”環境,運行Spyder。
第二步,導入擴展包。
import numpy as np from keras.datasets import mnist from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense, Activation, Convolution2D, MaxPooling2D, Flatten from keras.optimizers import Adam
第三步,載入MNIST數據及預處理。
X_train.reshape(-1, 1, 28, 28) / 255
將每個像素點進行標準化處理,從0-255轉換成0-1的范圍。
np_utils.to_categorical(y_train, nb_classes=10)
調用up_utils將類標轉換成10個長度的值,如果數字是3,則會在對應的地方標記為1,其他地方標記為0,即{0,0,0,1,0,0,0,0,0,0}。
由于MNIST數據集是Keras或TensorFlow的示例數據,所以我們只需要下面一行代碼,即可實現數據集的讀取工作。如果數據集不存在它會在線下載,如果數據集已經被下載,它會被直接調用。
# 下載MNIST數據 # training X shape (60000, 28x28), Y shape (60000, ) # test X shape (10000, 28x28), Y shape (10000, ) (X_train, y_train), (X_test, y_test) = mnist.load_data() # 數據預處理 # 參數-1表示樣例的個數 1表示灰度照片(3對應RGB彩色照片) 28*28表示像素長度和寬度 X_train = X_train.reshape(-1, 1, 28, 28) / 255 # normalize X_test = X_test.reshape(-1, 1, 28, 28) / 255 # normalize # 將類向量轉化為類矩陣 數字 5 轉換為 0 0 0 0 0 1 0 0 0 0 矩陣 y_train = np_utils.to_categorical(y_train, num_classes=10) y_test = np_utils.to_categorical(y_test, num_classes=10)
第四步,創建神經網絡第一層及池化層。
小方塊的長度和寬度是5,in size為1是圖片的厚度,輸出的高度是32。conv1輸出的大小為28 * 28 * 32,因為padding采用“SAME”的形式,conv1輸出值為32,故厚度也為32,長度和寬度相同為28。而由于POOLING處理設置的strides步長為2,故其輸出大小也有變化,其結果為14 * 14 * 32。
核心代碼如下。卷積層利用Convolution2D,池化層利用MaxPooling2D。
nb_filters表示濾波器,其值為32,每個濾波器掃描之后都會產生一個特征
nb_row表示寬度5
nb_col表示高度5
border_mode表示過濾,采用same方式(Padding method)
input_shape表示輸入形狀,1個高度,28個長度,28個寬度
#---------------------------創建第一層神經網絡--------------------------- # 創建CNN model = Sequential() # Conv layer 1 output shape (32, 28, 28) # 第一層利用Convolution2D卷積 model.add(Convolution2D( filters = 32, # 32個濾波器 nb_row = 5, # 寬度 nb_col = 5, # 高度 border_mode = 'same', # Padding method input_shape = (1, 28, 28), # 輸入形狀 channels height width )) # 增加神經網絡激活函數 model.add(Activation('relu')) # Pooling layer 1 (max pooling) output shape (32, 14, 14) # 池化層利用MaxPooling2D model.add(MaxPooling2D( pool_size = (2, 2), # 向下取樣 strides = (2,2), # 取樣跳2個 padding='same', # Padding method ))
為了防止跨度太大,丟失東西太多,這里添加了POOLING處理,strides值為2,減小跨度。最終得到結果的形狀都一樣,但它能保留更多的圖片信息。
第五步,創建第二層神經網絡及取樣。
conv2定義的patch為5*5,傳入大小為32,傳出大小為64,不斷將其變厚,類似于下圖所示。圖片最早的厚度為1(MNIST數據集是黑白圖片,如果是彩色則為3),接著第一層厚度變成32,第三層厚度增長為64。
此時conv2的輸出結果為14 * 14 * 64,第二層POOLING處理會繼續縮小一半,pool2輸出結果為7 * 7 * 64,高度不變。
# Conv layer 2 output shape (64, 14, 14) model.add(Convolution2D(64, 5, 5, border_mode='same')) model.add(Activation('relu')) # Pooling layer 2 (max pooling) output shape (64, 7, 7) model.add(MaxPooling2D(pool_size = (2, 2), border_mode='same'))
第六步,構建全連接層。
輸入值為conv2 layer的輸出值7 * 7 * 64,輸出值為1024,讓其變得更高更厚。接著第二個全連接層輸出結果為分類的10個類標。
# Fully connected layer 1 input shape (64 * 7 * 7) = (3136), output shape (1024) model.add(Flatten()) # 將三維層拉直 model.add(Dense(1024)) # 全連接層 model.add(Activation('relu')) # 激勵函數 # Fully connected layer 2 to shape (10) for 10 classes model.add(Dense(10)) # 輸出10個單位 model.add(Activation('softmax')) # 分類激勵函數
這里簡單總結下神經網絡:
conv1 layer:經過卷積和POOLING處理,最終輸出14 * 14 * 32
conv2 layer:經過卷積和POOLING處理,最終輸出7 * 7 * 64
func1 layer:平常使用的神經網絡,輸入7 * 7 * 64,最終輸出1024
func2 layer:平常使用的神經網絡,輸入1024,最終輸出10,代表10個數字,即為prediction
第七步,定義優化器并激活神經網絡,接著進行訓練預測,并輸出相應結果。
# 優化器 optimizer adam = Adam(lr=1e-4) # We add metrics to get more results you want to see # 激活神經網絡 model.compile(optimizer=adam, # 加速神經網絡 loss='categorical_crossentropy', # 損失函數 metrics=['accuracy']) # 計算誤差或準確率 print('Training') model.fit(X_train, y_train, epochs=1, batch_size=64,) # 訓練次數及每批訓練大小 print('Testing') loss, accuracy = model.evaluate(X_test, y_test) print('\ntest loss: ', loss) print('\ntest accuracy: ', accuracy)
2.完整代碼
# -*- coding: utf-8 -*- """ Created on Wed Feb 19 19:47:37 2020 @author: xiuzhang Eastmount CSDN Wuhan Fighting! """ import numpy as np from keras.datasets import mnist from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense, Activation, Convolution2D, MaxPooling2D, Flatten from keras.optimizers import Adam #---------------------------載入數據及預處理--------------------------- # 下載MNIST數據 # training X shape (60000, 28x28), Y shape (60000, ) # test X shape (10000, 28x28), Y shape (10000, ) (X_train, y_train), (X_test, y_test) = mnist.load_data() # 數據預處理 # 參數-1表示樣例的個數 1表示灰度照片(3對應RGB彩色照片) 28*28表示像素長度和寬度 X_train = X_train.reshape(-1, 1, 28, 28) / 255 # normalize X_test = X_test.reshape(-1, 1, 28, 28) / 255 # normalize # 將類向量轉化為類矩陣 數字 5 轉換為 0 0 0 0 0 1 0 0 0 0 矩陣 y_train = np_utils.to_categorical(y_train, num_classes=10) y_test = np_utils.to_categorical(y_test, num_classes=10) #---------------------------創建第一層神經網絡--------------------------- # 創建CNN model = Sequential() # Conv layer 1 output shape (32, 28, 28) # 第一層利用Convolution2D卷積 model.add(Convolution2D( filters = 32, # 32個濾波器 nb_row = 5, # 寬度 nb_col = 5, # 高度 border_mode = 'same', # Padding method input_shape = (1, 28, 28), # 輸入形狀 channels height width )) # 增加神經網絡激活函數 model.add(Activation('relu')) # Pooling layer 1 (max pooling) output shape (32, 14, 14) # 池化層利用MaxPooling2D model.add(MaxPooling2D( pool_size = (2, 2), # 向下取樣 strides = (2,2), # 取樣跳2個 padding='same', # Padding method )) #---------------------------創建第二層神經網絡--------------------------- # Conv layer 2 output shape (64, 14, 14) model.add(Convolution2D(64, 5, 5, border_mode='same')) model.add(Activation('relu')) # Pooling layer 2 (max pooling) output shape (64, 7, 7) model.add(MaxPooling2D(pool_size = (2, 2), border_mode='same')) #-----------------------------創建全連接層------------------------------ # Fully connected layer 1 input shape (64 * 7 * 7) = (3136), output shape (1024) model.add(Flatten()) # 將三維層拉直 model.add(Dense(1024)) # 全連接層 model.add(Activation('relu')) # 激勵函數 # Fully connected layer 2 to shape (10) for 10 classes model.add(Dense(10)) # 輸出10個單位 model.add(Activation('softmax')) # 分類激勵函數 #--------------------------------訓練和預測------------------------------ # 優化器 optimizer adam = Adam(lr=1e-4) # We add metrics to get more results you want to see # 激活神經網絡 model.compile(optimizer=adam, # 加速神經網絡 loss='categorical_crossentropy', # 損失函數 metrics=['accuracy']) # 計算誤差或準確率 print('Training') model.fit(X_train, y_train, epochs=1, batch_size=64,) # 訓練次數及每批訓練大小 print('Testing') loss, accuracy = model.evaluate(X_test, y_test) print('\ntest loss: ', loss) print('\ntest accuracy: ', accuracy)
3.運行結果
訓練一個批次的結果如下圖所示,最終誤差loss為“0.2520788”,正確率為“0.92650”。
訓練兩個批次的結果如下圖所示,最終誤差loss為“0.156024”,正確率為“0.95590”。
訓練六個批次的結果如下圖所示,最終誤差loss為“0.07606”,正確率為“0.97500”。可以看到誤差不斷減小,正確率不斷提高,說明CNN在不斷學習。真正做神經網絡實驗時,我們會針對不同的參數和樣本、算法進行比較,也希望這篇文章對您有幫助。
三.總結
寫到這里,這篇文章就結束了。本文主要通過Keras實現了一個CNN分類學習的案例,并詳細介紹了卷積神經網絡原理知識。最后,希望這篇基礎性文章對您有所幫助,如果文章中存在錯誤或不足之處,還請海涵~作為人工智能的菜鳥,我希望自己能不斷進步并深入,后續將它應用于圖像識別、網絡安全、對抗樣本等領域,指導大家撰寫簡單的學術論文,一起加油!
感恩能與大家在華為云遇見!
希望能與大家一起在華為云社區共同成長。原文地址:https://blog.csdn.net/Eastmount/article/details/104399015
(By:娜璋之家 Eastmount 2021-11-09 夜于武漢)
參考文獻:
Python 深度學習 神經網絡
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。