scipy 二维阵列的一维卷积

chy5wohz  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(202)

我有两个由信号集组成的阵列,都是16x90000阵列。换句话说,两个阵列中的每个阵列都有16个信号。我想对信号执行匹配滤波,逐行进行,将阵列1的第1行与阵列2的第1行进行相关,以此类推。我尝试使用scipy的signal.convolve2D,但速度非常慢。即使是一个2x90000的数组,也要花费几十秒的时间来卷积。我不确定是我的实现方式不对,还是有更有效的方法来实现我想要的结果。我知道数组很长,但我觉得它应该仍然是可以实现的。我有一种感觉convolve2d实际上是卷积到一个平方因子高于我想要的,并卷积行列太多,但我可能是误解了。
我的实现:

A.shape = (16,90000) # an array of 16 signals each 90000 samples long
B.shape = (16,90000) # another array of 16 signals each 90000 samples long

corr = sig.convolve2d(A,B,mode='same')

我还没喝多少咖啡所以我现在很可能是在犯傻。
请不要使用for循环。

siotufzp

siotufzp1#

由于您需要逐行关联信号,因此最基本的解决方案是:

import numpy as np
from scipy.signal import correlate

# sample inputs: A and B both have n signals of length m

n, m = 2, 5
A = np.random.randn(n, m)
B = np.random.randn(n, m)

C = np.vstack([correlate(a, b, mode="same") for a, b in zip(A, B)])

# [[-0.98455996  0.86994062 -1.1446486  -2.1751074  -0.59270322]
#  [ 1.7945015   1.51317292  1.74286042 -0.57750712 -1.9178488 ]]]

避免循环解决方案的一种方法是盗版深度学习库,比如PyTorch。Torch的Conv1d(虽然名为conv,但它可以有效地执行交叉相关)可以处理这种情况。

import torch
import torch.nn.functional as F

# Convert A and B to torch tensors
P = torch.from_numpy(A).unsqueeze(0) # (1, n, m)
Q = torch.from_numpy(B).unsqueeze(1) # (n, 1, m)

# Use conv1d --- with groups = n
def torch_correlate(A, B, n):
    with torch.no_grad():
        return F.conv1d(A, B, bias=None, stride=1, groups=n, padding="same").squeeze(0).numpy()

R = torch_correlate(P, Q, n)
# [[-0.98455996  0.86994062 -1.1446486  -2.1751074  -0.59270322]
#  [ 1.7945015   1.51317292  1.74286042 -0.57750712 -1.9178488 ]]

然而,我相信结果不会有任何显著的差异,因为分组可能也在内部使用了某种形式的迭代。(另外,从torch转换到numpy,再转换回来需要考虑的开销)。
我建议一般使用第一种方法。除非你正在处理非常大的信号,那么理论上你可以使用PyTorch版本在GPU上运行它非常快,这是你不能用常规的scipy版本做到的。

相关问题