scipy 如何仅在特定位置进行2D卷积?

ccgok5k5  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(158)

这个问题已经问了很多次了,但是我还是不能得到我想要的。想象一下

data=np.random.rand(N,N)   #shape N x N
kernel=np.random.rand(3,3) #shape M x M

我知道卷积通常意味着将核放在整个数据上,但在我的例子中,NM的数量级为10000。因此,我希望得到数据中特定位置的卷积值,比如(10、37),而不需要在所有位置进行不必要的计算。因此输出将只是一个数字。主要目标是减少计算和内存开销。有没有内置函数可以在最小的调整下做到这一点?

vlf7wbxs

vlf7wbxs1#

实际上,对特定位置应用卷积与data中的子矩阵与 * flip * 核本身的(逐点)乘法的元素之和一致。这里是一个可重现的示例。

代码

N = 1000
M = 3

np.random.seed(777)
data  = np.random.rand(N,N)   #shape N x N
kernel= np.random.rand(M,M)   #shape M x M

# Pointwise convolution = pointwise product

data[10:10+M,37:37+M]*kernel[::-1, ::-1]
>array([[0.70980514, 0.37426475, 0.02392947],
       [0.24387766, 0.1985901 , 0.01103323],
       [0.06321042, 0.57352696, 0.25606805]])

带输出

conv = np.sum(data[10:10+M,37:37+M]*kernel[::-1, ::-1])
conv
>2.45430578

kernelhere中所解释的卷积的定义翻转了,Warren Weckesser好心地指出了这一点。谢谢!
关键是要理解你提供的索引,我假设它指的是data中子矩阵的左上角,但是当M是奇数时,它也可以指中点。

概念

N=7M=3的另一个示例说明了这一思想,并在here中为内核提供了该示例

kernel = np.array([[3,0,-1], [2,0,1], [4,4,3]])

当翻转时产生

k[::-1,::-1]
> array([[ 3,  4,  4],
         [ 1,  0,  2],
         [-1,  0,  3]])

编辑1:

请注意,本视频中的讲师并没有明确提到,在逐点乘法之前需要翻转内核,以遵守卷积的数学正确定义。

编辑2

对于大的M和接近data边界的目标索引,可能会抛出ValueError: operands could not be broadcast together with shapes ...。为了防止这种情况,用零填充矩阵data可以防止这种情况(尽管这会增加内存需求)。

data   = np.pad(data, pad_width=M, mode='constant')

相关问题