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