【深度学习】人人都能看得懂的卷积神经网络——入门篇
近年來,卷積神經(jīng)網(wǎng)絡(luò)熱度很高,在短時(shí)間內(nèi),這類網(wǎng)絡(luò)成為了一種顛覆性技術(shù),打破了從文本、視頻到語音多個(gè)領(lǐng)域的大量最先進(jìn)的算法,遠(yuǎn)遠(yuǎn)超出其最初在圖像處理的應(yīng)用范圍。
卷積神經(jīng)網(wǎng)絡(luò)的一個(gè)例子
在客流預(yù)測、信號(hào)識(shí)別等時(shí),深度學(xué)習(xí)等作為新興的方法為我們提供了更多的選擇,在無需解釋參數(shù)意義時(shí),往往能提供更精確的預(yù)測結(jié)果。
因此,筆者將完成對(duì)卷積神經(jīng)網(wǎng)絡(luò)原理及使用的介紹,在文中將避免復(fù)雜的數(shù)學(xué)公式,以保證其可讀性。
ps:本文面向小白,大佬請(qǐng)繞道哦!
關(guān)于卷積神經(jīng)網(wǎng)絡(luò)
首先,簡單介紹一下,人工智能,機(jī)器學(xué)習(xí),神經(jīng)網(wǎng)絡(luò),深度學(xué)習(xí)這幾個(gè)概念的關(guān)聯(lián)。
人工智能:人類通過直覺可以解決,如圖像識(shí)別、語言理解、語音識(shí)別等,但計(jì)算機(jī)很難解決,而人工智能就是要解決這類問題。
機(jī)器學(xué)習(xí):如果一個(gè)任務(wù)可以在任務(wù)T上,隨著E的增加,效果P也隨著增加,那么認(rèn)為這個(gè)程序可以從經(jīng)驗(yàn)中學(xué)習(xí),即機(jī)器學(xué)習(xí)。
神經(jīng)網(wǎng)絡(luò):最初是一個(gè)生物學(xué)的概念,一般是指大腦神經(jīng)元,突觸等組成的網(wǎng)絡(luò),用于產(chǎn)生意識(shí),幫助生物思考和行動(dòng),后來人工智能受神經(jīng)網(wǎng)絡(luò)的啟發(fā),發(fā)展出了人工神經(jīng)網(wǎng)絡(luò)。所有的人工神經(jīng)網(wǎng)絡(luò)本質(zhì)上就是函數(shù)逼近問題,即曲面或函數(shù)的擬合。
深度學(xué)習(xí):深度學(xué)習(xí)是機(jī)器學(xué)習(xí)的新方向,其核心就是自動(dòng)將簡單的特征組合成功更加復(fù)雜的特征,并用這些特征解決問題。典型的深度學(xué)習(xí)模型就是很深層的神經(jīng)網(wǎng)絡(luò)。
概念之間的關(guān)聯(lián)如下圖所示。
本篇的主角卷積神經(jīng)網(wǎng)絡(luò)(Convolutional Neural Networks, CNN)就是典型的深度學(xué)習(xí)模型,也是一類包含卷積計(jì)算且具有深度結(jié)構(gòu)的前饋神經(jīng)網(wǎng)絡(luò)。
這里面有兩個(gè)概念需要解釋:
① 前饋神經(jīng)網(wǎng)絡(luò)
神經(jīng)網(wǎng)絡(luò)包括前饋神經(jīng)網(wǎng)絡(luò)和遞歸神經(jīng)網(wǎng)絡(luò)(也稱循環(huán)神經(jīng)網(wǎng)絡(luò))。前饋指的是網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)上不存在環(huán)或回路;遞歸則允許出現(xiàn)環(huán)路,如LSTM。
前饋神經(jīng)網(wǎng)絡(luò)多處理因果關(guān)系的預(yù)測;遞歸神經(jīng)網(wǎng)絡(luò)多處理時(shí)間序列的預(yù)測,網(wǎng)絡(luò)中的環(huán)狀結(jié)構(gòu),可以使其在t時(shí)刻的輸出狀態(tài)不僅與t時(shí)刻的輸入有關(guān),還與t-1時(shí)刻的網(wǎng)絡(luò)狀態(tài)有關(guān)。
雙隱層前饋神經(jīng)網(wǎng)絡(luò)
?
?
LSTM(具體參數(shù)可參考文末鏈接)
② 卷積
卷積是一種數(shù)學(xué)運(yùn)算方式,經(jīng)常用到的卷積方式包括一維卷積和二維卷積。這里的維度指樣本數(shù)據(jù)的維度。
某種程度上,一維卷積可以理解為移動(dòng)平均。如下圖,輸入信號(hào)序列,經(jīng)過濾波器(也稱卷積核)[-1,0,1],得到卷積結(jié)果。一般而言,濾波器的長度要遠(yuǎn)小于輸入數(shù)據(jù)的長度,圖中連接邊上的數(shù)字即濾波器的權(quán)重。將濾波器與輸入序列逐元素相乘以得到輸出序列中的一個(gè)元素。
一維卷積示例
同理,二維卷積的輸入數(shù)據(jù)是二維的,即圖像處理中經(jīng)常用到。如下圖所示,將濾波器與輸入矩陣元素逐個(gè)相乘以得到輸出矩陣的一個(gè)元素,陰影部分為參與卷積的部分?jǐn)?shù)據(jù)。
二維卷積示例
關(guān)于濾波器的大小、步幅、填充方式均可以自行設(shè)定。
一般而言,濾波器的維度要遠(yuǎn)小于輸入數(shù)據(jù)的維度;
濾波器的步幅,即每次滑動(dòng)的“距離”,可以是1,也可以大于1,大步幅意味著濾波器應(yīng)用的更少以及更小的輸出尺寸,而小步幅則能保留更多的信息;
至于填充方式,上述示例均為濾波器一旦觸及輸入數(shù)據(jù)的邊界即停止滑動(dòng),而另外一種方式是選擇零填充輸入,即用0補(bǔ)充輸出數(shù)據(jù),使輸出數(shù)據(jù)維度與輸入數(shù)據(jù)維度相同。
理解了卷積的含義,我們就可以更能清楚卷積的三個(gè)關(guān)鍵動(dòng)機(jī)。
① 感受野
感受野的定義是:卷積神經(jīng)網(wǎng)絡(luò)每一層輸出的特征圖(feature map)上的像素點(diǎn)在原始圖像上映射的區(qū)域大小。如二維卷積示例中的陰影部分即為感受野。
② 共享權(quán)重
假設(shè)想要從原始像素表示中獲得移除與輸入圖像中位置信息無關(guān)的相同特征的能力,一個(gè)簡單的直覺就是對(duì)隱藏層中的所有神經(jīng)元使用相同的權(quán)重。通過這種方式,每層將從圖像中學(xué)習(xí)到獨(dú)立于位置信息的潛在特征。
③ 池化(也稱匯聚)
池化一般包括最大池化和平均池化,如圖所示為最大池化的算例。可以看到池化其實(shí)就是對(duì)輸入數(shù)據(jù)分區(qū)域內(nèi)取最大值或平均值。池化的目的是總結(jié)一個(gè)特征映射的輸出,我們可以使用從單個(gè)特征映射產(chǎn)生的輸出的空間鄰接性,并將子矩陣的值聚合成單個(gè)輸出值,從而合成地描述與該物理區(qū)域相關(guān)聯(lián)的含義。
最大池化示例
一個(gè)典型的卷積神經(jīng)網(wǎng)絡(luò)是由卷積層、池化層、全連接層交叉堆疊而成。如下圖所示,圖中N個(gè)卷積塊,M個(gè)卷積層,b個(gè)池化層(匯聚層),K個(gè)全連接層。其中,ReLU為激活函數(shù)。
典型的卷積神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)
基于TensorFlow實(shí)現(xiàn)CNN
目前主流的深度學(xué)習(xí)框架包括:Theano、Caffe、TensorFlow、Pytorch、Keras。更多的深度學(xué)習(xí)框架可以參考:
https://en.wikipedia.org/wiki/Comparison_ of_deep_learning_software
TensorFlow的領(lǐng)先地位示意圖
關(guān)于TensorFlow和Keras的配置,可參考:
https://blog.csdn.net/lzy_shmily/article/details/80803433
本文將基于TensorFlow實(shí)現(xiàn)Mnist手寫數(shù)據(jù)集的識(shí)別和預(yù)測。
首先,簡單介紹下TensorFlow的張量及結(jié)構(gòu)。
① 張量(tensor)
可以理解為一個(gè)n維矩陣,所有類型的數(shù)據(jù),包括標(biāo)量(0-D)、向量(1-D)、矩陣(2-D)都是特殊的張量。在TensorFlow中,張量可以分為:常量,變量,占位符。
常量:即值不能改變的張量;
變量:變量需要初始化,但在會(huì)話中值也需要更新,如神經(jīng)網(wǎng)絡(luò)中的權(quán)重;
占位符:無需初始化,僅用于提供訓(xùn)練樣本,在會(huì)話中與feed_dict一起使用來輸入數(shù)據(jù)。
② TensorFlow結(jié)構(gòu)
可一分為二,計(jì)算圖的定義和執(zhí)行兩部分,彼此獨(dú)立。計(jì)算圖即包含節(jié)點(diǎn)和邊的網(wǎng)絡(luò),包括使用的數(shù)據(jù),即張量(常量、變量、占位符),以及需要執(zhí)行的所有計(jì)算(Operation Object,簡稱 OP)。
而Mnist手寫數(shù)據(jù)集則是機(jī)器學(xué)習(xí)的基礎(chǔ),包含手寫數(shù)字的圖像(0-9)及標(biāo)簽來說明它是哪個(gè)數(shù)字。同時(shí)對(duì)輸出y使用獨(dú)熱編碼(one_hot),如手寫數(shù)字8,編碼為 [0,0,0,0,0,0,0,0,1,0],即輸出有10位,且輸出僅有一位為1,其余均為0。
手寫數(shù)字8的圖像
下面是代碼部分,使用tensorflow框架搭建神經(jīng)網(wǎng)絡(luò)某種程度上可以理解為搭積木~
第一步:導(dǎo)入相應(yīng)包和數(shù)據(jù)
import tensorflow as tf # 導(dǎo)入MNIST 數(shù)據(jù) from tensorflow.examples.tutorials.mnist import input_data mnist = input_data.read_data_sets("MNIST_data/",one_hot=True) # 參數(shù)—:文件目錄,參數(shù)二:是否為one_hot向量注意:第一次導(dǎo)入數(shù)據(jù)時(shí),需要下載,耗時(shí)略長~
第二步:搭建網(wǎng)絡(luò)
數(shù)據(jù)的輸入部分
代碼中的x和y均為占位符,即用于提供樣本,后續(xù)會(huì)將網(wǎng)絡(luò)中涉及到的所有張量和op輸出,讀者可觀察其數(shù)據(jù)維度的變化。
# 設(shè)置計(jì)算圖輸入,定義占位符來存儲(chǔ)預(yù)測值和真實(shí)標(biāo)簽 x = tf.placeholder(tf.float32,[None,784]) # 輸入 # None表示樣本數(shù)量,之所以使用None,是因?yàn)?None 表示張量的第一維度可以是任意維度 y = tf.placeholder(tf.int32,[None,10]) #輸出 print("輸入占位符:",x) print("輸出占位符:",y)輸出:
輸入占位符: Tensor("Placeholder_10:0", shape=(?, 784), dtype=float32) 輸出占位符: Tensor("Placeholder_11:0", shape=(?, 10), dtype=int32)輸入層
輸出:
經(jīng)過reshape后的張量: Tensor("Reshape_13:0", shape=(?, 28, 28, 1), dtype=float32)卷積層1
輸出:
經(jīng)過卷積層1后的張量:Tensor("conv2d_8/Relu:0", shape=(?, 28, 28, 32), dtype=float32)(最大)池化層1
輸出:
經(jīng)過池化層1后的張量:Tensor("max_pooling2d_6/MaxPool:0", shape=(?, 14, 14, 32), dtype=float32)卷積層2
輸出:
經(jīng)過卷積層2后的張量:Tensor("conv2d_8/Relu:0", shape=(?, 28, 28, 32), dtype=float32)(最大)池化層2
輸出:
經(jīng)過池化層1后的張量:Tensor("max_pooling2d_7/MaxPool:0", shape=(?, 7, 7, 32), dtype=float32)平坦化
輸出:
經(jīng)過平坦化后的張量:Tensor("Reshape_14:0", shape=(?, 1568), dtype=float32)全連接層
輸出:
經(jīng)過全連接層后的張量: Tensor("dense_5/Relu:0", shape=(?, 1024), dtype=float32)Dropout層
輸出:
經(jīng)過dropout后的張量: Tensor("dropout_4/Identity:0", shape=(?, 1024), dtype=float32)輸出層
輸出:
CNN輸出張量:?Tensor("dense_6/BiasAdd:0",?shape=(?,?10),?dtype=float32)關(guān)于op (Operation Object),這里主要是誤差的反向傳播
第三步:執(zhí)行計(jì)算圖
# 創(chuàng)建會(huì)話 sess = tf.Session() # 初始化全局變量和局部變量,使用group結(jié)合兩個(gè)操作 init = tf.group(tf.global_variables_initializer(),tf.local_variables_initializer()) sess.run(init)training_iters = 2000 # 設(shè)置迭代次數(shù) step = 1 # 初始化更新次數(shù) batch_size = 128 display_step = 100 # 每更新50次計(jì)算一次損失和精度,并顯示 while step<=training_iters:batch_x,batch_y = mnist.train.next_batch(batch_size)sess.run(train_op,feed_dict={x:batch_x,y:batch_y})if step%display_step ==0:loss_train = sess.run(loss,feed_dict={x:batch_x,y:batch_y})print("step=%d, Train loss=%.4f"%(step,loss_train))step +=1#測試:打印20個(gè)預(yù)測值和真實(shí)值 test_x=mnist.test.images[:3000][:20] #image test_y=mnist.test.labels[:3000][:20] #labeltest_output=sess.run(y_CNN,{x:test_x}) inferenced_y=np.argmax(test_output,1) print(inferenced_y,'Inferenced numbers')#推測的數(shù)字 print(np.argmax(test_y,1),'Real numbers') sess.close()輸出:
step=100, Train loss=0.1030 step=200, Train loss=0.1106 step=300, Train loss=0.0607 step=400, Train loss=0.0722 step=500, Train loss=0.0408 step=600, Train loss=0.0366 step=700, Train loss=0.0167 step=800, Train loss=0.0268 step=900, Train loss=0.0632 step=1000, Train loss=0.0293 step=1100, Train loss=0.0124 step=1200, Train loss=0.0131 step=1300, Train loss=0.0153 step=1400, Train loss=0.0238 step=1500, Train loss=0.0200 step=1600, Train loss=0.0045 step=1700, Train loss=0.0118 step=1800, Train loss=0.0220 step=1900, Train loss=0.0029 step=2000, Train loss=0.0008 [7 2 1 0 4 1 4 9 5 9 0 6 9 0 1 5 9 7 5 4] Inferenced numbers [7 2 1 0 4 1 4 9 5 9 0 6 9 0 1 5 9 7 3 4] Real numbers從樣本結(jié)果可看出,網(wǎng)絡(luò)仍有較大的優(yōu)化空間,具體如何優(yōu)化,這個(gè)就留給讀者來思考~
關(guān)于卷積神經(jīng)網(wǎng)絡(luò)的介紹和簡單應(yīng)用就到此結(jié)束啦!如果您對(duì)卷積神經(jīng)網(wǎng)絡(luò)有什么不同的理解,歡迎交流~
參考文獻(xiàn):邱錫鵬. 《神經(jīng)網(wǎng)絡(luò)與深度學(xué)習(xí)》[M]. 清華大學(xué)出版社. 2019
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機(jī)器學(xué)習(xí)在線手冊(cè)深度學(xué)習(xí)筆記專輯《統(tǒng)計(jì)學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯 AI基礎(chǔ)下載機(jī)器學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)專輯獲取一折本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開:https://t.zsxq.com/yFQV7am本站qq群1003271085。加入微信群請(qǐng)掃碼進(jìn)群:總結(jié)
以上是生活随笔為你收集整理的【深度学习】人人都能看得懂的卷积神经网络——入门篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对Transformer,XLNet,A
- 下一篇: 【深度学习】深入浅出卷积神经网络及实现!