1. 程式人生 > 其它 >python人臉識別專案之學習筆記(五):卷積神經網路

python人臉識別專案之學習筆記(五):卷積神經網路

1. 卷積神經網路

卷積神經網路(Convolutional Neural Network)簡稱CNN,CNN是所有深度學
習課程、書籍必教的模型,CNN在影像識別方面的為例特別強大,許多影像識別
的模型也都是以CNN的架構為基礎去做延伸。另外值得一提的是CNN模型也是
少數參考人的大腦視覺組織來建立的深度學習模型,學會CNN之後,對於學習其
他深度學習的模型也很有幫助,通過一個例子來講解CNN的原理以及使用CNN
來達成99%正確度的手寫字型識別。


從上面三張圖片我們可以看出,CNN架構簡單來說就是:圖片經過各兩次的
Convolution, Pooling, Fully Connected就是CNN的架構了,因此只要搞懂Convolution,
Pooling, Fully Connected三個部分的內容就可以完全掌握了CNN!

CNN在影象識別的案例:

假設給定一張圖(可能是字母X或者字母O),通過CNN即可識別出是X還是O,
如下圖所示,那怎麼做到的呢

提取特徵
如果字母X、字母O是固定不變的,那麼最簡單的方式就是影象之間的畫素一一
比對就行,但在現實生活中,字型都有著各個形態上的變化(例如手寫文字識
別),例如平移、縮放、旋轉、微變形等等,如下圖所示

我們的目標是對於各種形態變化的X和O,都能通過CNN準確地識別出來,這就涉
及到應該如何有效地提取特徵,作為識別的關鍵因子。

對於CNN來說,它是一小塊一小塊地來進行比對,在兩幅影象中大致相同的位置找到一些粗糙的特徵(小塊影象)進行匹配,相比起傳統的整幅圖逐一比對的方式,CNN的這種小塊匹配方式能夠更好的比較兩幅影象之間的相似性。如下圖:

以字母X為例,可以提取出三個重要特徵(兩個交叉線、一個對角線),
如下圖所示:

假如以畫素值"1"代表白色,畫素值"-1"代表黑色,則字母X的三個重要特徵如下:

卷積

當給定一張新圖時,CNN並不能準確地知道這些特徵到底要匹配原圖的哪些部分,所以它會在原圖
中把每一個可能的位置都進行嘗試,相當於把這個feature(特徵)變成了一個過濾器。這個用來匹
配的過程就被稱為卷積操作,這也是卷積神經網路名字的由來。

在本案例中,要計算一個feature(特徵)和其在原圖上對應的某一小塊的結果,只需將兩個
小塊內對應位置的畫素值進行乘法運算,然後將整個小塊內乘法運算的結果累加起來,最後
再除以小塊內畫素點總個數即可(注:也可不除以總個數的)。

如果兩個畫素點都是白色(值均為1),那麼1 * 1 = 1,如果均為黑色 ,那麼 (-1)*(-1) = 1,也就是說,每一對能夠匹配上的畫素,其相乘結果為1。類似地,任何不匹配的畫素相乘結果為-1。具體過程如下(第一個、第二個……、最後一個畫素的匹配結果):

根據卷積的計算方式,第一塊特徵匹配後的卷積計算如下,結果為1

對於其它位置的匹配,也是類似(例如中間部分的匹配)

計算之後的卷積如下

以此類推,對三個特徵影象不斷地重複著上述過程,通過每一個feature(特徵)的卷積操作,
會得到一個新的二維陣列,稱之為feature map。其中的值,越接近1表示對應位置和feature
的匹配越完整,越是接近-1,表示對應位置和feature的反面匹配越完整,而值接近0的表示對
應位置沒有任何匹配或者說沒有什麼關聯。如下圖所示:

程式碼實現

tf.nn.conv2d (input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)
'引數:
input : 輸入的要做卷積的圖片,要求為一個張量,shape為 [ batch, in_height, in_weight, in_channel ],其中batch為圖片的數量,in_height 為圖片高度,in_weight 為圖片寬度,in_channel 為圖片的通道數,灰度圖該值為1,彩色圖為3
filter: 相當於CNN中的卷積核,它要求是一個Tensor,具有[filter_height, filter_width, in_channels, out_channels]這樣的shape,具體含義是[卷積核的高度,卷積核的寬度,影象通道數,卷積核個數],要求型別與引數input相同,有一個地方需要注意,第三維in_channels,就是引數input的第四維;
卷積時在影象每一維的步長,這是一個一維的向量,長度4
padding: string型別的量,只能是”SAME”,”VALID”其中之一,這個值決定了不同的卷積方式
use_cudnn_on_gpu:bool型別,是否使用cudnn加速,預設為true結果返回一個Tensor,這個輸出,就是我們常說的feature map


分析:

  1. 需要做卷積的圖片是一個3*3的彩色圖片
import tensorflow as tf

input = tf.constant(
    [
        [
            [
                [100., 100., 100.],
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.],
                [100., 100., 100.],
                [100., 100., 100.]
            ],
            [
                [100., 100., 100.],
                [100., 100., 100.],
                [100., 100., 100.],
            ]
        ]
    ]
)

filter = tf.constant(
    [
        [
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ],
        [
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ],
            [
                [0.5, 0.1],
                [0.5, 0.1],
                [0.5, 0.1]
            ]
        ],
    ]
)

result1 = tf.nn.convolution(input, filter, padding='VALID')
result2 = tf.nn.convolution(input, filter, padding='SAME')

with tf.Session() as sess:
    print(sess.run([result1, result2]))