矩阵和向量的卷积,即不同维度的输入

Convolution of a matrix and a vector i.e. inputs of different dimensions

这是this one的后续问题:

我有 Matlab 代码,我想将其转换为 Python,其中包括 conv2。我可以在 Python 中模仿它的行为:

import numpy as np
from scipy import signal

def conv2(x, y, mode='same'):
    return np.rot90(signal.convolve2d(np.rot90(x, 2), np.rot90(y, 2), mode=mode), 2)

如果我再打电话

f = [[2, 3, 4], [1, 6, 7]]
g = [[9, 1, 0], [2, 5, 8], [1, 3, 3]]

print conv2(f, g)
print conv2(g, f)

它给我的输出与 Matlab 的相同

conv2([[2,3,4];[1,6,7]], [[9,1,0];[2,5,8];[1,3,3]], 'same')
conv2([[9,1,0];[2,5,8];[1,3,3]], [[2,3,4];[1,6,7]], 'same')

然而,Matlab 的 conv2 也适用于一个参数是矢量的情况。例如,

conv2([[2,3,4];[1,6,7]], [9,1,0]', 'same')

给出:

   11   57   67
    1    6    7

不过我无法在 Python 中获得此输出,因为标准函数通常需要相同的输入维度。例如:

signal.convolve(f, [9, 1, 0])

产量

ValueError: in1 and in2 should have the same dimensionality

signal.convolve2d(f, [9, 1, 0])

ValueError: object of too small depth for desired array

如何为不同维度的输入实现相同的输出?

似乎最简单的解决方案就是使用例如numpy.expand_dims 然后传递一个二维输入。对于上面的示例,它将是:

g2 = np.array([9, 1, 0])
g2 = np.expand_dims(g2, 0)

然后

conv2(f, g2.transpose())

给我

array([[11, 57, 67],
       [ 1,  6,  7]])

这与 Matlab 输出相同。

只需将一维数组转换为二维数组即可。

In [71]: f = np.array([[2, 3, 4], [1, 6, 7]])
    ...: g = np.array([[9, 1, 0], [2, 5, 8], [1, 3, 3]])
In [72]: h = np.array([9,1,0])
In [73]: conv2(f,g)
Out[73]: 
array([[ 71, 108,  51],
       [ 26,  71, 104]])
In [74]: conv2(f, h[:,None])
Out[74]: 
array([[11, 57, 67],
       [ 1,  6,  7]])
In [75]: h[:,None]
Out[75]: 
array([[9],
       [1],
       [0]])

在 Octave 中,您的 [9,1,0]' 是一个列矩阵:

>> conv2([[2,3,4];[1,6,7]], [9,1,0]', 'same')
ans =
   11   57   67
    1    6    7

>> [9,1,0]'
ans =
   9
   1
   0

在 MATLAB 中,一切都是二维的(或更高)。 numpy 允许一维数组。

应用于 h

np.rot90 与从 [[9,1,0]]:

创建为二维数组的 h[None,:]h 相同
In [76]: np.rot90(h[:,None])
Out[76]: array([[9, 1, 0]])

在 octave/matlab 中,您可以通过在开始处设置列矩阵来跳过转置:

conv2([[2,3,4];[1,6,7]], [9;1;0], 'same')

相当于 numpy 的是:

conv2(f,[[9],[1],[0]])