【问题标题】:Autocorrelation of a multidimensional array in numpynumpy中多维数组的自相关
【发布时间】:2011-05-29 01:09:25
【问题描述】:

我有一个二维数组,即一个序列数组,它们也是数组。对于每个序列,我想计算自相关,因此对于 (5,4) 数组,我会得到 5 个结果,或维度为 (5,7) 的数组。

我知道我可以遍历第一个维度,但这很慢,也是我最后的手段。还有其他方法吗?

谢谢!

编辑:

根据选择的答案加上 mtrw 的评论,我有以下功能:

def xcorr(x):
  """FFT based autocorrelation function, which is faster than numpy.correlate"""
  # x is supposed to be an array of sequences, of shape (totalelements, length)
  fftx = fft(x, n=(length*2-1), axis=1)
  ret = ifft(fftx * np.conjugate(fftx), axis=1)
  ret = fftshift(ret, axes=1)
  return ret

请注意,在我的代码中长度是一个全局变量,所以一定要声明它。我也没有将结果限制为实数,因为我还需要考虑复数。

【问题讨论】:

  • 如果你能添加length的计算就太好了

标签: python numpy


【解决方案1】:

使用FFT-based autocorrelation:

import numpy
from numpy.fft import fft, ifft

data = numpy.arange(5*4).reshape(5, 4)
print data
##[[ 0  1  2  3]
## [ 4  5  6  7]
## [ 8  9 10 11]
## [12 13 14 15]
## [16 17 18 19]]
dataFT = fft(data, axis=1)
dataAC = ifft(dataFT * numpy.conjugate(dataFT), axis=1).real
print dataAC
##[[   14.     8.     6.     8.]
## [  126.   120.   118.   120.]
## [  366.   360.   358.   360.]
## [  734.   728.   726.   728.]
## [ 1230.  1224.  1222.  1224.]]

我对你关于具有维度 (5, 7) 的答案的陈述有点困惑,所以也许有一些我不理解的重要内容。

编辑:根据 mtrw 的建议,一个不环绕的填充版本:

import numpy
from numpy.fft import fft, ifft

data = numpy.arange(5*4).reshape(5, 4)
padding = numpy.zeros((5, 3))
dataPadded = numpy.concatenate((data, padding), axis=1)
print dataPadded
##[[  0.   1.   2.   3.   0.   0.   0.   0.]
## [  4.   5.   6.   7.   0.   0.   0.   0.]
## [  8.   9.  10.  11.   0.   0.   0.   0.]
## [ 12.  13.  14.  15.   0.   0.   0.   0.]
## [ 16.  17.  18.  19.   0.   0.   0.   0.]]
dataFT = fft(dataPadded, axis=1)
dataAC = ifft(dataFT * numpy.conjugate(dataFT), axis=1).real
print numpy.round(dataAC, 10)[:, :4]
##[[   14.     8.     3.     0.     0.     3.     8.]
## [  126.    92.    59.    28.    28.    59.    92.]
## [  366.   272.   179.    88.    88.   179.   272.]
## [  734.   548.   363.   180.   180.   363.   548.]
## [ 1230.   920.   611.   304.   304.   611.   920.]]

必须有更有效的方法来做到这一点,特别是因为自相关是对称的,我没有利用这一点。

【讨论】:

  • +1 表示基于 FFT 的方法。至于 (5,7) 形状的答案,您已经计算了循环相关性 (en.wikipedia.org/wiki/…)。只需用 3 个零填充每一行,这样光谱乘法就不会环绕,您就会得到原始问题所要求的内容。
  • 谢谢大家,这看起来很有希望!对于零填充,我只需要将 n=(length*2-1) 添加到 fft??
  • 对于具有 n 个变量的一维序列,此解决方案将填充 n-1 个零。因此,如果数据形状为 (5, 121),则填充形状为 (5, 120)
  • 我将用答案更新我的问题,并选择您的作为“官方”答案,因为它引导我找到了正确的解决方案,并附有 mtrw 的评论。谢谢大家!
  • 使用 fft 的 'n=' 选项而不是手动填充的良好调用。
【解决方案2】:

对于非常大的数组,n = 2 ** p 变得很重要,其中 p 是一个整数。这将为您节省大量时间。例如:

def xcorr(x):
    l = 2 ** int(np.log2(x.shape[1] * 2 - 1))
    fftx = fft(x, n = l, axis = 1)
    ret = ifft(fftx * np.conjugate(fftx), axis = 1)
    ret = fftshift(ret, axes=1)
    return ret

这可能会给您带来环绕错误。不过,对于大型数组,自相关在边缘附近应该是微不足道的。

【讨论】:

  • 如果你能添加length的计算那就太好了——它只是x.shape[1]吗?
【解决方案3】:

也许这只是一种偏好,但我想遵循定义。我个人觉得这样更容易一些。这是我对任意 nd 数组的实现。

从 itertools 导入产品 从 numpy 导入空,滚动 def autocorrelate(x): """ Compute the multidimensional autocorrelation of an nd array. input: an nd array of floats output: an nd array of autocorrelations """ # used for transposes t = roll(range(x.ndim), 1) # pairs of indexes # the first is for the autocorrelation array # the second is the shift ii = [list(enumerate(range(1, s - 1))) for s in x.shape] # initialize the resulting autocorrelation array acor = empty(shape=[len(s0) for s0 in ii]) # iterate over all combinations of directional shifts for i in product(*ii): # extract the indexes for # the autocorrelation array # and original array respectively i1, i2 = asarray(i).T x1 = x.copy() x2 = x.copy() for i0 in i2: # clip the unshifted array at the end x1 = x1[:-i0] # and the shifted array at the beginning x2 = x2[i0:] # prepare to do the same for # the next axis x1 = x1.transpose(t) x2 = x2.transpose(t) # normalize shifted and unshifted arrays x1 -= x1.mean() x1 /= x1.std() x2 -= x2.mean() x2 /= x2.std() # compute the autocorrelation directly # from the definition acor[tuple(i1)] = (x1 * x2).mean() return acor

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-01
    • 2019-05-17
    • 2014-06-15
    • 2014-08-08
    • 1970-01-01
    • 2020-10-02
    相关资源
    最近更新 更多