做爲人類,咱們不斷地經過眼睛來觀察和分析周圍的世界,咱們不須要刻意的「努力」思考,就能夠對所看到的一切作出預測,並對它們採起行動。當咱們看到某些東西時,咱們會根據咱們過去學到的東西來標記每一個對象。爲了說明這些狀況,請看下面這張圖片: html
這就是咱們成天下意識地作的事情。咱們看到事物,而後標記,進行預測和識別行爲。可是咱們怎麼作到這些的呢?咱們怎麼能解釋咱們看到的一切?前端
大天然花費了5億多年的時間來建立一個系統來實現這一目標。眼睛和大腦之間的合做,稱爲主要視覺通路,是咱們理解周圍世界的緣由。 git
當您看到一個物體時,您眼中的光感覺器會經過視神經將信號發送到正在處理輸入的主視覺皮層。在初級視覺皮層,使眼睛看到的東西的感受。github
全部這一切對咱們來講都很天然。咱們幾乎沒有想到咱們可以識別咱們生活中看到的全部物體和人物的特殊性。神經元和大腦鏈接的深層複雜層次結構在記憶和標記物體的過程當中起着重要做用。算法
想一想咱們如何學習例如傘是什麼。或鴨子,燈,蠟燭或書。一開始,咱們的父母或家人告訴咱們直接環境中物體的名稱。咱們經過給咱們的例子瞭解到。慢慢地,但咱們開始在咱們的環境中愈來愈多地認識到某些事情。它們變得如此廣泛,以致於下次咱們看到它們時,咱們會當即知道這個物體的名稱是什麼。他們成爲咱們世界的模型一部分。flask
與孩子學會識別物體的方式相似,咱們須要在可以歸納輸入並對以前從未見過的圖像進行預測以前,展現數百萬張圖片的算法。數組
計算機以與咱們不一樣的方式「看到」東西的。他們的世界只包括數字。每一個圖像均可以表示爲二維數字數組,稱爲像素。bash
可是它們以不一樣的方式感知圖像,這一事實並不意味着咱們沒法訓練他們的識別模式,就像咱們同樣如何識別圖像。咱們只須要以不一樣的方式思考圖像是什麼。 網絡
卷積神經網絡受到大腦的啓發。DH Hubel和TN Wiesel在20世紀50年代和60年代對哺乳動物大腦的研究提出了哺乳動物如何在視覺上感知世界的新模型。他們代表貓和猴的視覺皮層包括在其直接環境中專門響應神經元的神經元。架構
在他們的論文中,他們描述了大腦中兩種基本類型的視覺神經元細胞,每種細胞以不一樣的方式起做用:簡單細胞(S細胞)和複合細胞(C細胞)。
例如,當簡單單元格將基本形狀識別爲固定區域和特定角度的線條時,它們就會激活。複雜細胞具備較大的感覺野,其輸出對野外的特定位置不敏感。
複雜細胞繼續對某種刺激作出反應,即便它在視網膜上的絕對位置發生變化。在這種狀況下,複雜指的是更靈活。
在視覺中,單個感受神經元的感覺區域是視網膜的特定區域,其中某些東西將影響該神經元的發射(即,將激活神經元)。每一個感受神經元細胞都有類似的感覺野,它們的田地覆蓋着。
此外,層級【hierarchy 】的概念在大腦中起着重要做用。信息按順序存儲在模式序列中。的新皮層,它是大腦的最外層,以分層方式存儲信息。它存儲在皮質柱中,或者在新皮層中均勻組織的神經元分組。
1980年,一位名爲Fukushima的研究員提出了一種分層神經網絡模型。他稱之爲新認知。該模型的靈感來自簡單和複雜細胞的概念。neocognitron可以經過了解物體的形狀來識別模式。
後來,1998年,捲心神經網絡被Bengio,Le Cun,Bottou和Haffner引入。他們的第一個卷積神經網絡稱爲LeNet-5,可以對手寫數字中的數字進行分類。
卷積神經網絡(Convolutional Neural Network)簡稱CNN,CNN是全部深度學習課程、書籍必教的模型,CNN在影像識別方面的爲例特別強大,許多影像識別的模型也都是以CNN的架構爲基礎去作延伸。另外值得一提的是CNN模型也是少數參考人的大腦視覺組織來創建的深度學習模型,學會CNN以後,對於學習其餘深度學習的模型也頗有幫助,本文主要講述了CNN的原理以及使用CNN來達成99%正確度的手寫字體識別。 CNN的概念圖以下:
卷積運算就是將原始圖片的與特定的Feature Detector(filter)
作卷積運算(符號⊗
),卷積運算就是將下圖兩個3x3
的矩陣做相乘後再相加,如下圖爲例0 *0 + 0*0 + 0*1+ 0*1 + 1 *0 + 0*0 + 0*0 + 0*1 + 0*1 =0
中間的Feature Detector(Filter)會隨機產生好幾種(ex:16種),Feature Detector的目的就是幫助咱們萃取出圖片當中的一些特徵(ex:形狀),就像人的大腦在判斷這個圖片是什麼東西也是根據形狀來推測
咱們在輸入上進行了屢次卷積,其中每一個操做使用不一樣的過濾器。這致使不一樣的特徵映射。最後,咱們將全部這些特徵圖放在一塊兒,做爲卷積層的最終輸出。
就像任何其餘神經網絡同樣,咱們使用激活函數使輸出非線性。在卷積神經網絡的狀況下,卷積的輸出將經過激活函數。這多是ReLU激活功能
這裏還有一個概念就是步長,Stride是每次卷積濾波器移動的步長。步幅大小一般爲1,意味着濾鏡逐個像素地滑動。經過增長步幅大小,您的濾波器在輸入上滑動的間隔更大,所以單元之間的重疊更少。
下面的動畫顯示步幅大小爲1。
添加一層零值像素以使用零環繞輸入,這樣咱們的要素圖就不會縮小。除了在執行卷積後保持空間大小不變,填充還能夠提升性能並確保內核和步幅大小適合輸入。
可視化卷積層的一種好方法以下所示,最後咱們以一張動圖解釋下卷積層到底作了什麼
在卷積層以後,一般在CNN層之間添加池化層。池化的功能是不斷下降維數,以減小網絡中的參數和計算次數。這縮短了訓練時間並控制過分擬合。
最多見的池類型是max pooling,它在每一個窗口中佔用最大值。須要事先指定這些窗口大小。這會下降特徵圖的大小,同時保留重要信息。
Max Pooling主要的好處是當圖片整個平移幾個Pixel的話對判斷上徹底不會形成影響,以及有很好的抗雜訊功能。
基本上全鏈接層的部分就是將以前的結果平坦化以後接到最基本的神經網絡了
下面這部分主要是關於如何使用tensorflow實現CNN以及手寫字體識別的應用
# CNN 代碼
def convolutional(x,keep_prob):
def conv2d(x,W):
return tf.nn.conv2d(x,W,[1,1,1,1],padding='SAME')
def max_pool_2x2(x):
return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
def weight_variable(shape):
initial=tf.truncated_normal(shape,stddev=0.1)
return tf.Variable(initial)
def bias_variable(shape):
initial=tf.constant(0.1,shape=shape)
return tf.Variable(initial)
x_image=tf.reshape(x,[-1,28,28,1])
W_conv1=weight_variable([5,5,1,32])
b_conv1=bias_variable([32])
h_conv1=tf.nn.relu(conv2d(x_image,W_conv1)+b_conv1)
h_pool1=max_pool_2x2(h_conv1)
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
# full_connetion
W_fc1=weight_variable([7*7*64,1024])
b_fc1=bias_variable([1024])
h_pool2_flat=tf.reshape(h_pool2,[-1,7*7*64])
h_fc1=tf.nn.relu(tf.matmul(h_pool2_flat,W_fc1)+b_fc1)
# dropout 隨機扔掉一些值,防止過擬合
h_fc1_drop=tf.nn.dropout(h_fc1,keep_prob)
W_fc2=weight_variable([1024,10])
b_fc2=bias_variable([10])
y=tf.nn.softmax(tf.matmul(h_fc1_drop,W_fc2)+b_fc2)
return y,[W_conv1,b_conv1,W_conv2,b_conv2,W_fc1,b_fc1,W_fc2,b_fc2]
複製代碼
你們稍微對tensorflow的代碼有些基礎,理解上面這部分基本上沒有難度,而且基本也是按照咱們前面概念圖中的邏輯順序實現的。
最終按照慕課網上的學習資料TensorFlow與Flask結合打造手寫體數字識別,實現了一遍CNN,比較曲折的地方是前端,以及如何將訓練的模型與flask整合,最後項目效果以下:
最後說本身的兩點感觸吧: