keras卷积处理rgb输入_CNN卷积神经网络模型搭建
前言
前段時間嘗試使用深度學習來識別評測過程中的圖片,以減少人力成本。目前是在深度學習框架Keras(后端使用TensorFlow)下搭建了一個CNN卷積神經網絡模型,下面就如何搭建一個最簡單的數字圖像識別模型做下介紹。
模型的建立
(1) 卷積層(convolution layer):至于什么是卷積大家可以自己去找資料看看,這里重點講講Convolution2D()函數。根據keras官方文檔描述,2D代表這是一個2維卷積,其功能為對2維輸入進行滑窗卷積計算。我們的數字圖像尺寸為28*28,擁有長、寬兩維,所以在這里我們使用2維卷積函數計算卷積。所謂的滑窗計算,其實就是利用卷積核逐個像素、順序進行計算,如下圖:
上圖選擇了最簡單的均值卷積核,3x3大小,我們用這個卷積核作為掩模對前面4x4大小的圖像逐個像素作卷積運算。首先我們將卷積核中心對準圖像第一個像素,在這里就是像素值為237的那個像素。卷積核覆蓋的區域(掩模之稱即由此來),其下所有像素取均值然后相加:
C(1) = 0 * 0.5 + 0 * 0.5 + 0 * 0.5 + 0 * 0.5 + 237 * 0.5 + 203 * 0.5 + 0 * 0.5 + 123 * 0.5 + 112 * 0.5結果直接替換卷積核中心覆蓋的像素值,接著是第二個像素、然后第三個,從左至右,由上到下……以此類推,卷積核逐個覆蓋所有像素。整個操作過程就像一個滑動的窗口逐個滑過所有像素,最終生成一副尺寸相同但已經過卷積處理的圖像。上圖我們采用的是均值卷積核,實際效果就是將圖像變模糊了。顯然,卷積核覆蓋圖像邊界像素時,會有部分區域越界,越界的部分我們以0填充,如上圖。對于此種情況,還有一種處理方法,就是丟掉邊界像素,從覆蓋區域不越界的像素開始計算。像上圖,如果采用丟掉邊界像素的方法,3x3的卷積核就應該從第2行第2列的像素(值為112)開始,到第3行第3列結束,最終我們會得到一個2x2的圖像。這種處理方式會丟掉圖像的邊界特征;而第一種方式則保留了圖像的邊界特征。在我們建立的模型中,卷積層采用哪種方式處理圖像邊界,卷積核尺寸有多大等參數都可以通過Convolution2D()函數來指定:
#第一個卷積層,4個卷積核,每個卷積核大小5*5。1表示輸入的圖片的通道,灰度圖為1通道。model.add(Conv2D(4, (5, 5), border_mode='valid',input_shape=(1, 28, 28), data_format='channels_first'))
第一個卷積層包含4個卷積核,每個卷積核大小為5x5,border_mode值為“same”意味著我們采用保留邊界特征的方式滑窗,而值“valid”則指定丟掉邊界像素(數字圖像邊緣是沒用的,所以用vaild)。根據keras開發文檔的說明,當我們將卷積層作為網絡的第一層時,我們還應指定input_shape參數,顯式地告知輸入數據的形狀,對我們的程序來說,input_shape的值為(1, 28, 28),代表28x28的灰度圖。
PS:“channels_first”或“channels_last”之一,代表圖像的通道維的位置。該參數是Keras 1.x中的image_dim_ordering,“channels_last”對應原本的“tf”,“channels_first”對應原本的“th”。以128x128的RGB圖像為例,“channels_first”應將數據組織為(3,128,128),而“channels_last”應將數據組織為(128,128,3)。該參數的默認值是~/.keras/keras.json中設置的值,若從未設置過,則為“channels_last”。
(2) 激活函數層:這里講一下最簡單的relu(Rectified Linear Units,修正線性單元)函數,它的數學形式如下:
?(x) = max(0, x)這個函數非常簡單,其輸出一目了然,小于0的輸入,輸出全部為0,大于0的則輸入與輸出相等。該函數的優點是收斂速度快,除了它,keras庫還支持其它幾種激活函數,如下:
softplus
softsign
tanh
sigmoid
hard_sigmoid
linear
它們的函數式、優缺點網絡上有很多資料,大家自己去查。對于不同的需求,我們可以選擇不同的激活函數,這也是模型訓練可調整的一部分,運用之妙,存乎一心,請自忖之。另外再交代一句,其實激活函數層按照我們前文所講,其屬于人工神經元的一部分,所以我們亦可以在構造層對象時通過傳遞activation參數設置,如下:
model.add(Convolution2D(4, (5, 5), border_mode='valid',input_shape=(1, 28, 28), data_format='channels_first'))model.add(Activation('tanh'))
#通過傳遞activation參數設置,與上兩行代碼的作用相同
model.add(Convolution2D(4, (5, 5), border_mode='valid',input_shape=(1, 28, 28), data_format='channels_first'), activation='tanh')
(3) 池化層(pooling layer):池化層存在的目的是縮小輸入的特征圖,簡化網絡計算復雜度;同時進行特征壓縮,突出主要特征。我們通過調用MaxPooling2D()函數建立了池化層,這個函數采用了最大值池化法,這個方法選取覆蓋區域的最大值作為區域主要特征組成新的縮小后的特征圖:
顯然,池化層與卷積層覆蓋區域的方法不同,前者按照池化尺寸逐塊覆蓋特征圖,卷積層則是逐個像素滑動覆蓋。對于我們輸入的28x28特征圖來說,經過2x2池化后,圖像變為14x14大小。
model.add(MaxPooling2D(pool_size=(2, 2)))(4)Dropout層:隨機斷開一定百分比的輸入神經元鏈接,以防止過擬合。那么什么是過擬合呢?一句話解釋就是訓練數據預測準確率很高,測試數據預測準確率很低,用圖形表示就是擬合曲線較尖,不平滑。導致這種現象的原因是模型的參數很多,但訓練樣本太少,導致模型擬合過度。為了解決這個問題,Dropout層將有意識的隨機減少模型參數,讓模型變得簡單,而越簡單的模型越不容易產生過擬合。代碼中Dropout()函數只有一個輸入參數——指定拋棄比率,范圍為0~1之間的浮點數,其實就是百分比。這個參數亦是一個可調參數,我們可以根據訓練結果調整它以達到更好的模型成熟度。
#本樣例沒有使用到,詳見官方文檔keras.layers.core.Dropout(rate, noise_shape=None, seed=None)
(5)Flatten層:截止到Flatten層之前,在網絡中流動的數據還是多維的(對于我們的程序就是2維的),經過多次的卷積、池化、Dropout之后,到了這里就可以進入全連接層做最后的處理了。全連接層要求輸入的數據必須是一維的,因此,我們必須把輸入數據“壓扁”成一維后才能進入全連接層,Flatten層的作用即在于此。該層的作用如此純粹,因此反映到代碼上我們看到它不需要任何輸入參數。
(6)全連接層(dense layer):全連接層的作用就是用于分類或回歸,對于我們來說就是分類。keras將全連接層定義為Dense層,其含義就是這里的神經元連接非常“稠密”。我們通過Dense()函數定義全連接層。這個函數的一個必填參數就是神經元個數,其實就是指定該層有多少個輸出。在我們的代碼中,第一個全連接層(#14 Dense層)指定了512個神經元,也就是保留了512個特征輸出到下一層。這個參數可以根據實際訓練情況進行調整,依然是沒有可參考的調整標準,自調之。
#全連接層,先將前一層輸出的二維特征圖flatten為一維的。#Dense就是隱藏層。16就是上一層輸出的特征圖個數。4是根據每個卷積層計算出來的:(28-5+1)得到24,(24-3+1)/2得到11,(11-3+1)/2得到4
#全連接有128個神經元節點,初始化方式為normal
model.add(Flatten())
model.add(Dense(128, init='normal'))
model.add(Activation('tanh'))
(7)分類層:全連接層最終的目的就是完成我們的分類要求:0到9,模型構建代碼的最后兩行完成此項工作:
#Softmax分類,輸出是10類別model.add(Dense(10, init='normal'))
model.add(Activation('softmax'))
總結
以上是生活随笔為你收集整理的keras卷积处理rgb输入_CNN卷积神经网络模型搭建的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python制作考试系统_Python系
- 下一篇: oreo另一个意思_记一次有意思的统计(