Tensorflow快餐教程(9) - 卷积
摘要:?卷積的計算方法
卷積
卷積就是滑動中提取特征的過程
在數學中,卷積convolution是一種函數的定義。它是通過兩個函數f和g生成第三個函數的一種數學算子,表征函數f與g經過翻轉和平移的重疊部分的面積。其定義為:
h(x)=f(x)?g(x)=∫∞?∞f(t)g(x?t)dth(x)=f(x)?g(x)=∫?∞∞f(t)g(x?t)dt
也可以用星號表示:h(x)=(f?g)(x)h(x)=(f?g)(x)
卷積的第一個參數(上例中的f),通常叫做輸入。第二個參數(函數g)叫做核函數kernel function。輸出有時候叫特征映射feature map.
也可以定義離散形式的卷積:
h(x)=(f?g)(x)=∑∞t=?∞f(t)g(x?t)h(x)=(f?g)(x)=∑t=?∞∞f(t)g(x?t)
g(x-t)是變化的,而f(t)是固定不動的。我們可以將卷積理解成是g(x-t)滑動過程中對f(t)進行采樣。
我們一般可以用f(x)=wx+bf(x)=wx+b來作為核函數提取特征
我們來舉個小例子說明一下卷積對于特征提取的過程。
假設有一個5*5的矩陣做為輸入:
array([[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.],[1., 1., 1., 1., 1.]], dtype=float32)y=wx+b我們取w為3*3的全1矩陣,b=0。
這樣我們計算左邊第一個3*3的小塊,得1?1+1?1+1?1+1?1+1?1+1?1+1?1+1?1+1?1=91?1+1?1+1?1+1?1+1?1+1?1+1?1+1?1+1?1=9。
以此類推,最后我們得到一個
[[9,9,9],
[9,9,9],
[9,9,9]]
的矩陣。
相當于我們把一個55的黑白矩陣壓縮成了33的灰度矩陣。
全是1的話大家看不太清楚,我們選一個對角矩陣再來計算一下:
array([[1., 0., 0., 0., 0.],[0., 1., 0., 0., 0.],[0., 0., 1., 0., 0.],[0., 0., 0., 1., 0.],[0., 0., 0., 0., 1.]], dtype=float32)計算卷積之后的結果為:
[[3,2,1], [2,3,2], [1,2,3]]圖像縮小了之后,仍然是主對角線最黑?;咎卣鬟€是被提取出來了。
填充Padding
從前面對角線的例子可以看出,由于圖片中間的點被計算的次數多,而邊緣上的點計算的次數少,所以明明右上角和左下角都是0,提取完特征之后被中間的1給影響了。
我們可以選擇給這個55的矩陣外邊加上一圈padding,將其變成77的矩陣。
我們再重新計算一下卷積,獲取下面一個5*5的新矩陣:
[[2,2,1,0,0],[2,3,2,1,0],[1,2,3,2,1],[0,1,2,3,2],[0,0,1,2,2]]這樣邊緣的0就被識別出來了。Padding的最主要作用就是讓邊界變得更清晰。
步幅Stride
上面我們求卷積的時候,每次向右移到一步,這個移動距離就是Stride。
比如我們想把圖片壓縮得更狠一點,取得更高的壓縮率,我們就可以加大步幅。
卷積用Tensorflow實現
上面知識儲備已足,我們開始用Tensorflow來計算卷積吧。
首先是輸入,按照Tensorflow的要求,我們得把5*5的,resize成[1,5,5,1]格式的,如下:
c array([[[[1.],[0.],[0.],[0.],[0.]],[[0.],[1.],[0.],[0.],[0.]],[[0.],[0.],[1.],[0.],[0.]],[[0.],[0.],[0.],[1.],[0.]],[[0.],[0.],[0.],[0.],[1.]]]], dtype=float32)然后我們還需要準備卷積核,先生成一個3*3全1矩陣:
a2 = sess.run(tf.ones([3,3])) a2 array([[1., 1., 1.],[1., 1., 1.],[1., 1., 1.]], dtype=float32)然后將其reshape成[3,3,1,1]格式的:
a3 = sess.run(tf.reshape(a2,[3,3,1,1])) a3 array([[[[1.]],[[1.]],[[1.]]],[[[1.]],[[1.]],[[1.]]],[[[1.]],[[1.]],[[1.]]]], dtype=float32)步幅我們設成[1,1,1,1],其實就是x軸1,y軸1,前面和后面的1先不用管它。padding設成'SAME':
a1 = tf.nn.conv2d(c,a3,strides=[1,1,1,1],padding='SAME') sess.run(a1) array([[[[2.],[2.],[1.],[0.],[0.]],[[2.],[3.],[2.],[1.],[0.]],[[1.],[2.],[3.],[2.],[1.]],[[0.],[1.],[2.],[3.],[2.]],[[0.],[0.],[1.],[2.],[2.]]]], dtype=float32)結果看起來不爽的話,我們再重新將其reshape成[5,5]的:
a5 = tf.reshape(a4,[5,5]) sess.run(a5) array([[2., 2., 1., 0., 0.],[2., 3., 2., 1., 0.],[1., 2., 3., 2., 1.],[0., 1., 2., 3., 2.],[0., 0., 1., 2., 2.]], dtype=float32)嗯,是不是跟我們手動計算的一樣呢?恭喜你,已經學會卷積啦!
池化層
池化層跟卷積也很像,但是計算要簡單得多。池化主要有兩種,一種是取最大值,一種是取平均值。而卷積是要做矩陣內積運算的。
我們以2*2最大池化為例,處理一下上節加了padding的卷積
[[2,2,1,0,0],[2,3,2,1,0],[1,2,3,2,1],[0,1,2,3,2],[0,0,1,2,2]]最大池化就是取最大值,比如[[2,2],[2,3]]就取3。結果如下:
[[3,3,2,1],[3,3,3,2],[2,3,3,3],[1,2,3,3,]]可以看到,池化雖然進一步丟失了信息,但是基本規律還是不變的。
池化被認為可以提高泛化性,對于微小的變動不敏感。比如對于少量的平移,旋轉或者縮放保持同樣的識別。但是,池化層不是必須的。
在Tensorflow中,可以用tf.nn.max_pool來實現最大池功能。
首先我們要把圖片resize成(-1,高,寬,1)這樣格式的:
b = tf.reshape(a,[-1,5,5,1]) c = sess.run(b) array([[[[1.],[0.],[0.],[0.],[0.]],[[0.],[1.],[0.],[0.],[0.]],[[0.],[0.],[1.],[0.],[0.]],[[0.],[0.],[0.],[1.],[0.]],[[0.],[0.],[0.],[0.],[1.]]]], dtype=float32)然后我們用步幅為2。2*2窗口計算max pooling。
命令如下:
四元組中我們不必管第一個和最后一個,中間兩個是高和寬。ksize和步幅皆如此。
運行結果是一個3*3的對角陣:
卷積網絡的結構
卷積神經網絡也叫卷積網絡,是一種善于處理網格數據的網絡。典型應用是處理一維網格數據語音和二維網格數據圖像。只要是在網絡結構中使用了哪怕一層的卷積層,就叫做卷積神經網絡。
與之前介紹的神經網絡都是全連接網絡,即每一層的每個節點都是上一層的所有節點相連接。
而卷積網絡一般是五種連接結構的組合:
卷積網絡簡史
上節深度學習簡史中我們提到過,第一個卷積網絡模型于1989年由Yann LeCun提出。卷積網絡的主要概念如為什么要卷積,為什么要降采樣,什么是徑向基函數RBF(Radial Basis Function)等。
10年后的1998年,Yann LeCun設計了LeNet網絡。在論文《Gradient-Based Learning Applied to Document Recognition》中提出了LeNet-5的模型,結構如下:
論文原文在:http://yann.lecun.com/exdb/publis/pdf/lecun-98.pdf
但是,正如我們前面介紹的,當時還是SVM輝煌的時代。
轉折點要到十幾年后的2012年,Hinton的學生Alex Krizhevsky發明的AlexNet之時。AlexNet在2012年的圖像分類競賽中將Top-5錯誤率從上一年的25.8%降到15.3%.
AlexNet成功之后,大家的研究熱情空前高漲。主要方向有網絡加深和功能增強。
話說ImageNet真是個群英薈萃的地方。2012年第一名是Alex。2013的第一名是Matthew Zeiler,之前講過他提出的AdaGrad。
值得一提的是,在最近幾年的ImageNet中,華人屢創佳績。比如2016年的冠軍被公安部第三研究所搜神團隊獲得,成績是錯誤率2.99%。
作者:lusing
原文鏈接
本文為云棲社區原創內容,未經允許不得轉載。
總結
以上是生活随笔為你收集整理的Tensorflow快餐教程(9) - 卷积的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【2018新年巨献】像阿里巴巴一样高效工
- 下一篇: 青年PM倪超:想让程序员多一点点幸福感