目錄
舉例
結論
參考資料
在一些書籍和博客中所講的卷積(一個卷積核和輸入的對應位置相乘,然后累加)不是真正意義上的卷積。根據離散卷積的定義,卷積核是需要旋轉180的。
按照定義來說,一個輸入和一個卷積核做卷積操作的流程是:
①卷積核旋轉180
②對應位置相乘,然后累加
舉例 |
下面這個圖是常見的卷積運算圖:
中間的卷積核,其實是已經旋轉過180度的
即,做卷積的兩個矩陣其實是
[[2, 1, 0, 2, 3],
[9, 5, 2, 2, 0],
[2, 3, 4, 5, 6],
[1, 2, 3, 1, 0],
[0, 4, 4, 2, 8]]
和
[[1, 0, -1],
[1, 0, -1],
[1, 0, -1]]
沒有旋轉只有乘積求和就不叫卷積運算。
但是,在tensorflow中覺得這樣很糾結,所以干脆定義的卷積核直接就是旋轉后的卷積核,所以tensorflow可以直接對應位置相乘,然后相加

import tensorflow as tf # [batch, in_height, in_width, in_channels]
input = tf.constant([ [2, 1, 0, 2, 3], [9, 5, 4, 2, 0], [2, 3, 4, 5, 6], [1, 2, 3, 1, 0], [0, 4, 4, 2, 8], ], tf.float32) input = tf.reshape(input, [1, 5, 5, 1]) #定義旋轉180后的卷積核 # [filter_height, filter_width, in_channels, out_channels]
kernel = tf.constant([ [-1, 0, 1], [-1, 0, 1], [-1, 0, 1] ], tf.float32) kernel = tf.reshape(kernel, [3, 3, 1, 1]) print(tf.Session().run(tf.nn.conv2d(input,kernel,[1,1,1,1],"VALID"))) [[[[-5.] [ 0.] [ 1.]] [[-1.] [-2.] [-5.]] [[ 8.] [-1.] [ 3.]]]]
而在scipy中,是按照嚴格的卷積定義來的,你定義了一個卷積核后,scipy要先將你的卷積核旋轉180度,然后才對應位置相乘,再相加。

import numpy as np from scipy import signal input = np.array([ [2, 1, 0, 2, 3], [9, 5, 4, 2, 0], [2, 3, 4, 5, 6], [1, 2, 3, 1, 0], [0, 4, 4, 2, 8] ]) #定義未經旋轉的卷積核
kernel = np.array([ [1, 0, -1], [1, 0, -1], [1, 0, -1] ]) # kernel1 = np.flip(kernel1)
print(signal.convolve(input, kernel, mode="valid")) [[-5 0 1] [-1 -2 -5] [ 8 -1 3]]
結論 |
如果你定義的是旋轉180度后的卷積核,那就直接對應位置相乘再相加
如果你定義的是未經旋轉的卷積核,那需要先旋轉180,再對應位置相乘再相加
市面上的參考書大部分描述的卷積核都是旋轉后的卷積核,我的博客中也是這樣,因為這樣更容易理解,不然做一次卷積,你是很難直觀看出來結果的。
參考資料 |
什么!卷積要旋轉180度?!
https://www.jianshu.com/p/8dfe02b61686
二維卷積的計算原理
https://wenku.baidu.com/view/f55e1bc6f90f76c661371ac5.html