標準的卷積過程可以看上圖,乙個2×2的卷積核在卷積時,對應影象區域中的所有通道均被同時考慮,問題在於,為什麼一定要同時考慮影象區域和通道?我們為什麼不能把通道和空間區域分開考慮?
深度可分離卷積提出了一種新的思路:對於不同的輸入channel採取不同的卷積核進行卷積。
順便一提,tf的實現可以接收rate引數,即可以採用空洞卷積的方式進行操作。
我們定義一張4*4的雙通道
import tensorflow as tf
img1 = tf.constant(value=[[[[1],[2],[3],[4]],
[[1],[2],[3],[4]],
[[1],[2],[3],[4]],
[[1],[2],[3],[4]]]],dtype=tf.float32)
img2 = tf.constant(value=[[[[1],[1],[1],[1]],
[[1],[1],[1],[1]],
[[1],[1],[1],[1]],
[[1],[1],[1],[1]]]],dtype=tf.float32)
img = tf.concat(values=[img1,img2],axis=3)
img
使用3*3的卷積核,輸入channel為2,輸出channel為2(卷積核數目為2),
filter1 = tf.constant(value=0, shape=[3,3,1,1],dtype=tf.float32)
filter2 = tf.constant(value=1, shape=[3,3,1,1],dtype=tf.float32)
filter3 = tf.constant(value=2, shape=[3,3,1,1],dtype=tf.float32)
filter4 = tf.constant(value=3, shape=[3,3,1,1],dtype=tf.float32)
filter_out1 = tf.concat(values=[filter1,filter2],axis=2)
filter_out2 = tf.concat(values=[filter3,filter4],axis=2)
filter = tf.concat(values=[filter_out1,filter_out2],axis=3)
filter
同時執行卷積操作,和深度可分離卷積操作,
out_img_conv = tf.nn.conv2d(input=img, filter=filter, strides=[1,1,1,1], padding='valid')
out_img_depthwise = tf.nn.depthwise_conv2d(input=img,
filter=filter, strides=[1,1,1,1], rate=[1,1], padding='valid')
with tf.session() as sess:
res1 = sess.run(out_img_conv)
res2 = sess.run(out_img_depthwise)
print(res1, '\n', res1.shape)
print(res2, '\n', res2.shape)
對比輸出shape,depthwise_conv2d輸出的channel數目為in_channel * 卷積核數目,每乙個卷積核對應通道都會對對應的channel進行一次卷積,所以輸出通道數更多,[[[[ 9. 63.][ 9. 81.]]
[[ 9. 63.]
[ 9. 81.]]]]
(1, 2, 2, 2) # 《----------
[[[[ 0. 36. 9. 27.]
[ 0. 54. 9. 27.]]
[[ 0. 36. 9. 27.]
[ 0. 54. 9. 27.]]]]
(1, 2, 2, 4)# 《----------
看到這裡大家可能會誤解深度可分離卷積的輸出通道數大於普通卷積,其實這只是「分離」部分,後面還有組合的步驟,而普通卷積只不過直接完成了組合:通過對應點相加,將四個卷積中間結果合併為卷積核個數(這裡是2)
合併過程如下,可分離卷積中的合併過程變成可學習的了,使用乙個1*1的普通卷積進行特徵合併,
point_filter = tf.constant(value=1, shape=[1,1,4,4],dtype=tf.float32)
out_img_s = tf.nn.conv2d(input=out_img_depthwise, filter=point_filter, strides=[1,1,1,1], padding='valid')
with tf.session() as sess:
res3 = sess.run(out_img_s)
print(res3, '\n', res3.shape)
[[[[ 72. 72. 72. 72.][ 90. 90. 90. 90.]]
[[ 72. 72. 72. 72.]
[ 90. 90. 90. 90.]]]]
(1, 2, 2, 4)
out_img_se = tf.nn.separable_conv2d(input=img,
depthwise_filter=filter,
pointwise_filter=point_filter,
strides=[1,1,1,1], rate=[1,1], padding='valid')
with tf.session() as sess:
print(sess.run(out_img_se))
假設輸入通道數為3,要求輸出通道數為256,兩種做法:[[[[ 72. 72. 72. 72.][ 90. 90. 90. 90.]]
[[ 72. 72. 72. 72.]
[ 90. 90. 90. 90.]]]]
(1, 2, 2, 4)
1.直接接乙個3×3×256的卷積核,參數量為:3×3×3×256 = 6,912
2.dw操作,分兩步完成,參數量為:3×3×3 + 3×1×1×256 = 795(3個特徵層*(3*3的卷積核)),卷積深度引數通常取為1
深度可分離卷積將以往普通卷積操作同時考慮通道和區域改變(卷積先只考慮區域,然後再考慮通道),實現了通道和區域的分離。
深度可分離卷積
下面這個文章介紹了深度可分離卷積是怎麼做的 本文的很多內容都是在這兩個文章的基礎上整理的。卷積基礎 描述乙個二維矩陣,使用row col。三維的,使用channel row col。四維則多了乙個引數 batch channel row col。batch channel row col的邏輯順序則...
深度可分離卷積
如果乙個卷積核代表乙個影象的屬性的話,上圖的方法就只能提取到乙個屬性。那麼如果想要多個屬性就需要多個卷積核 上圖中是最常見的卷積方法,使用多個卷積核來提取多個屬性。但是存在引數量過大的情況 先用三個卷積核對三個通道分別卷積,再對得到的結果進行1x1的卷積,這時候只要增加1 1卷積核的個數就能對應的增...
深度可分離卷積
3.實際應用 假設輸入層為乙個大小為64 64畫素 三通道彩色。經過乙個包含4個filter的卷積層,最終輸出4個feature map,且尺寸與輸入層相同。整個過程可以用下圖來概括 卷積層共有4個filters,每個filter有3個kernel,每個kernel的大小為3x3,因此卷積層的引數數...