生活随笔
收集整理的這篇文章主要介紹了
卷积神经网络(CNN)详解及TensorFlow2代码实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
卷積神經網絡名字聽著挺嚇人,本文用通俗易懂的方式解釋。人人都能看懂。
文章目錄
- 卷積是什么
- 一、卷積神經網絡介紹
- 卷積層--提取局部圖片特征
- 擴充--padding,保持卷積后圖片的長和寬保持不變
- 池化層---降低維度,降低模型復雜度和計算量
- flatten展平--讓多維數據變成一個巨大的一維向量
- 全連接層--輸出結果
- 二、TensorFlow2代碼實現
- 1.導入數據
- 2.用TensorFlow2構建一個CNN網絡
- 總結
卷積是什么
卷積神經網絡就是傳統神經網絡運用了矩陣卷積的技術。
二維線性卷積:
矩陣舉例:
(部分內容摘抄自此文)
現在有一張圖片(下圖左) 和一個kernel核(下圖中間)。通過卷積可以得到下圖右的結果。
我們知道,圖片實際上就是一個巨大的數值矩陣,也就是我們常說的像素。一張灰色圖片就是一個巨大的二維矩陣,矩陣中每個元素表示黑白的程度,可以理解為就是一個數學矩陣。
二維卷積:從二維矩陣中拿到第一個值,即圖示中的標紅框1,1所在的位置對上卷積核kernel 中心位置,即圖示中的紅色框(卷積核就是一個矩陣),對應位置的值與矩陣元素相乘最后求和,得到的值便是新的值-8(計算方法見上文矩陣求卷積運算),以此類推,取得所有位置的新值,最后圖片的最外層填上0就可以了。二維卷積得到的大小取決與卷積核,而卷積核大小一般是奇數大小(例3×3, 5×5),表示取像素值取決周圍一圈的像素值,取決的權重由卷積核決定,提取該區域特定特征。
一、卷積神經網絡介紹
卷積神經網絡(CNN)可用于使機器可視化事物并執行諸如圖像分類,圖像識別,對象檢測,實例分割等任務。這是CNN最常見的領域,如字跡識別等。
卷積層–提取局部圖片特征
圖片有RGB三個顏色通道,因此輸入是3層,由于3個輸入通道(紅色R,綠色G和藍色B),我們看到的任何圖像都是3通道圖像??梢岳斫鉃?層,因此卷積核也是3層,相當于兩個3*3的魔方對應的9個元素相乘,最后9個乘積相加。因此,卷積核相當于使用3層二維(長和寬)過濾器,圖像的通道數(層數)和過濾器層數相同。
與2D卷積操作類似,我們將在水平方向上滑動過濾器。每次移動過濾器時,我們都將獲取整個圖片三個通道(3層)的加權平均值,即RGB值的加權鄰域。由于我們僅在兩個維度上滑動內核-從左到右,從上到下,此操作的輸出將是2D輸出。
假設我們有大小為7x7的2D輸入,并且正在從圖像的左上角開始在圖像上應用3x3的濾鏡。當我們從左到右,從上到下在圖像上滑動內核時,很明顯,輸出小于輸入,即5x5。
如果我們希望輸出與輸入大小相同怎么辦?
如果原始輸入的大小為7x7,我們也希望輸出大小為7x7。因此,在那種情況下,我們可以做的是在輸入周圍均勻添加一個人工填充(值為零),這樣我們就可以將過濾器K(3x3)放置在圖像像素點上,并計算鄰居的加權平均值。
一個卷積核就是提取一個特征,因此,為了充分提取圖片的特征,我們需要多個卷積核對圖片進行特征提取,這就叫卷積核的深度,得到的結果就是多個2D輸出,堆疊在一起,就有多層輸出。如圖:
理解了這個圖,才能理解最后那個卷積神經網絡的架構圖。多層卷積會導致這種彩色的層數增加。
擴充–padding,保持卷積后圖片的長和寬保持不變
通過在輸入周圍添加一圈(零)這種人工填充,我們可以將輸出的形狀與輸入保持相同。如果我們有一個更大的過濾器K(5x5),那么我們需要應用零填充的數量也會增加,這樣我們就可以保持相同的輸出大小。在此過程中,輸出的大小與輸出的大小相同,因此命名為Padding。原文見此鏈接
池化層—降低維度,降低模型復雜度和計算量
獲得了特征圖,通常我們將執行一個稱為Pooling operation的操作。由于學習圖像中存在的復雜關系所需的隱藏層數將很大。我們應用池化操作來減少輸入特征的表示,從而降低網絡所需的計算能力。
一旦獲得輸入的特征圖,我們將在特征圖上應用確定形狀的過濾器,以從特征圖的該部分獲得最大值。這稱為最大池化。這也稱為子采樣,因為從內核覆蓋的特征圖的整個部分中,我們正在對一個最大值進行采樣。
flatten展平–讓多維數據變成一個巨大的一維向量
我們得到了多個粉色的卷積結果,是個多維的,如卷積層那節最后的那個圖所示。
可是我們預測的結果是一維的,比如二分類,不是0就是1,多維的數據怎么得到一維的輸出呢?
簡單嘛,把多維的數據全部攤平,成一個一維的數組,就像你把很多個魔方,一個個的掰下來,排成一排。魔方就是多維的啊,你不就是把多個多維的數組,變成一維的數組了嗎?
全連接層–輸出結果
一旦我們對圖像的特征表示進行了一系列的卷積和pooling操作(最大合并或平均合并,也稱下采樣)。我們將最終池化層的輸出展平為一個向量,并將其通過具有不同數量隱藏層的全連接層(前饋神經網絡)傳遞,最后經過多層的深度神經網絡進行擬合。
最后,完全連接層的輸出將通過所需大小的Softmax層。Softmax層輸出概率分布的向量,這有助于執行圖像分類任務。在數字識別器問題(如上所示)中,輸出softmax層具有10個神經元,可將輸入分類為10個類別之一(0–9個數字)。如果是個二分類問題,則Softmax層就是2個神經元,分別輸出0,1,所以最后的Softmax層是根據最終結果需要分多少類來確定的。
如果是2分類,最后那個softmax成就是只有兩個神經元,表示2類輸出。
二、TensorFlow2代碼實現
1.導入數據
我們用TensorFlow2自帶的mnist測試手寫的0-9數字,然后判定他具體寫的是哪個數字。
向導入數據,新建一個MNISTLoader的類。
代碼如下(命名為testData.py):
import numpy
as np
import tensorflow
as tf
class MNISTLoader():def __init__(self
):mnist
= tf
.keras
.datasets
.mnist
(self
.train_data
,self
.train_label
),(self
.test_data
,self
.test_label
) = mnist
.load_data
()self
.train_data
= np
.expand_dims
(self
.train_data
.astype
(np
.float)/255.0,axis
=-1) self
.test_data
= np
.expand_dims
(self
.test_data
.astype
(np
.float32
) / 255.0, axis
=-1) self
.train_label
= self
.train_label
.astype
(np
.int32
) self
.test_label
= self
.test_label
.astype
(np
.int32
) self
.num_train_data
, self
.num_test_data
= self
.train_data
.shape
[0], self
.test_data
.shape
[0] def get_batch(self
, batch_size
):index
= np
.random
.randint
(0, self
.num_train_data
, batch_size
) return self
.train_data
[index
, :], self
.train_label
[index
]
2.用TensorFlow2構建一個CNN網絡
代碼結構如下:
1、定義超參數
2、定于模型結構
3、對模型進行訓練
4、預測測試集并測試準確度
import numpy
as np
import tensorflow
as tf
from testData
import *
import time
class CNN(tf
.keras
.Model
):def __init__(self
):super().__init__
()self
.conv1
= tf
.keras
.layers
.Conv2D
(filters
=32, kernel_size
=[5,5], padding
='same', activation
= tf
.nn
.relu
)self
.pool1
= tf
.keras
.layers
.MaxPool2D
(pool_size
=[2,2],strides
=2) self
.conv2
= tf
.keras
.layers
.Conv2D
(filters
=64,kernel_size
=[5,5],padding
='same',activation
=tf
.nn
.relu
)self
.pool2
= tf
.keras
.layers
.MaxPool2D
(pool_size
=[2,2],strides
=2) self
.flatten
= tf
.keras
.layers
.Reshape
(target_shape
=(7*7*64,)) self
.dense1
= tf
.keras
.layers
.Dense
(units
=1024,activation
=tf
.nn
.relu
) self
.dense2
= tf
.keras
.layers
.Dense
(units
=10) def call(self
,inputs
):x
= self
.conv1
(inputs
) x
= self
.pool1
(x
) x
= self
.conv2
(x
) x
= self
.pool2
(x
) x
= self
.flatten
(x
) x
= self
.dense1
(x
) x
= self
.dense2
(x
) output
= tf
.nn
.softmax
(x
)return output
num_epochs
= 5
batch_size
= 50
learning_rate
= 0.001print('now begin the train, time is ')
print(time
.strftime
('%Y-%m-%d %H:%M:%S',time
.localtime
()))
model
= CNN
()
data_loader
= MNISTLoader
()
optimier
= tf
.keras
.optimizers
.Adam
(learning_rate
=learning_rate
)num_batches
= int(data_loader
.num_train_data
//batch_size
*num_epochs
)
for batch_index
in range(num_batches
):X
,y
= data_loader
.get_batch
(batch_size
)with tf
.GradientTape
() as tape
:y_pred
= model
(X
)loss
= tf
.keras
.losses
.sparse_categorical_crossentropy
(y_true
=y
,y_pred
=y_pred
)loss
= tf
.reduce_sum
(loss
)print("batch %d: loss %f"%(batch_index
,loss
.numpy
()))grads
= tape
.gradient
(loss
,model
.variables
)optimier
.apply_gradients
(grads_and_vars
=zip(grads
,model
.variables
))print('now end the train, time is ')
print(time
.strftime
('%Y-%m-%d %H:%M:%S', time
.localtime
()))
sparse_categorical_accuracy
= tf
.keras
.metrics
.SparseCategoricalAccuracy
()
num_batches_test
= int(data_loader
.num_test_data
//batch_size
)
for batch_index
in range(num_batches_test
):start_index
,end_index
= batch_index
*batch_size
,(batch_index
+1)*batch_sizey_pred
= model
.predict
(data_loader
.test_data
[start_index
:end_index
])sparse_categorical_accuracy
.update_state
(y_true
= data_loader
.test_label
[start_index
:end_index
],y_pred
=y_pred
)
print('test accuracy: %f'%sparse_categorical_accuracy
.result
())
print('now end the test, time is ')
print(time
.strftime
('%Y-%m-%d %H:%M:%S',time
.localtime
()))
運行的預測準確率能達到99.15%。太不可思議了。
輸出結果:
batch
5999: loss
0.094517
now end the train
, time
is
2021-03-18 17:15:46
test accuracy
: 0.991500
now end the test
, time
is
2021-03-18 17:16:05
總結
搭建一個卷積神經網絡只需要滿足:確定層數、按照卷積、激活、池化等流程定義每一層、層與層之間輸入輸出匹配,要輸出結果,就需要把2維甚至多維的矩陣展平成一個大的1維矩陣,然后用全連接又可以構建輸出端的多層神經網絡,最后輸出的那層用到了softmax函數進行分類,輸出的概率最大的那個結果,就是我們的預測結果。
因此實現一個卷積神經網絡的搭建。準確率已經相當不錯了。
總結
以上是生活随笔為你收集整理的卷积神经网络(CNN)详解及TensorFlow2代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。