Python 用numpy计算向量的自相关

Python 用numpy计算向量的自相关,python,numpy,statistics,stochastic-process,Python,Numpy,Statistics,Stochastic Process,我正在努力想出一种非模糊的、有效的方法,用numpy计算一组3D向量中的自相关函数 我在3d空间中有一组向量,保存在数组中 a = array([[ 0.24463039, 0.58350592, 0.77438803], [ 0.30475903, 0.73007075, 0.61165238], [ 0.17605543, 0.70955876, 0.68229821], [ 0.32425896, 0.57572195, 0.750

我正在努力想出一种非模糊的、有效的方法,用numpy计算一组3D向量中的自相关函数

我在3d空间中有一组向量,保存在数组中

a = array([[ 0.24463039,  0.58350592,  0.77438803],
       [ 0.30475903,  0.73007075,  0.61165238],
       [ 0.17605543,  0.70955876,  0.68229821],
       [ 0.32425896,  0.57572195,  0.7506    ],
       [ 0.24341381,  0.50183697,  0.83000565],
       [ 0.38364726,  0.62338687,  0.68132488]])
它们的自相关函数定义为

如果上面的图像不可用,公式也打印在下面: C(t,{v}n)=\frac1{n-t}\sum{i=0}^{n-1-t}\vec v_i\cdot\vec v_{i+t}


我正在努力以一种高效、不令人困惑的方式编写代码。我可以用两个嵌套的for循环来明确地计算,但这太慢了。通过使用numpy中的一个嵌入式函数,有一种快速的实现方法,但它们似乎使用了完全不同的相关函数定义。这里解决了一个类似的问题,但它不处理向量。你知道我该如何解决这个问题吗?

我在这里发布答案,以备其他人需要,因为我花了相当长的时间才找到可行的方法。我最终通过定义以下函数来解决这个问题

def vector_autocorrelate(t_array):
  n_vectors = len(t_array)
  # correlate each component indipendently
  acorr = np.array([np.correlate(t_array[:,i],t_array[:,i],'full') for i in xrange(3)])[:,n_vectors-1:]
  # sum the correlations for each component
  acorr = np.sum(acorr, axis = 0)
  # divide by the number of values actually measured and return
  acorr = np.array( [ val / (n_vectors - i) for i,val in enumerate(acorr)])
  return acorr

如果有人有更好的想法,我真的很想听听,因为我认为目前的想法还没有达到应有的紧凑程度。这总比什么都没有好,这就是为什么我在这里发布答案。

我在这里发布答案,以防其他人需要它,因为我花了相当长的时间才找到可行的方法。我最终通过定义以下函数来解决这个问题

def vector_autocorrelate(t_array):
  n_vectors = len(t_array)
  # correlate each component indipendently
  acorr = np.array([np.correlate(t_array[:,i],t_array[:,i],'full') for i in xrange(3)])[:,n_vectors-1:]
  # sum the correlations for each component
  acorr = np.sum(acorr, axis = 0)
  # divide by the number of values actually measured and return
  acorr = np.array( [ val / (n_vectors - i) for i,val in enumerate(acorr)])
  return acorr

如果有人有更好的想法,我真的很想听听,因为我认为目前的想法还没有达到应有的紧凑程度。不过总比什么都没有好,这就是我在这里发布它的原因。

NumPy例程适用于1D数组。作为“最小”改进,对规范化步骤使用矢量化操作(使用前一行到最后一行中的
np.arange
):

对于较大的数组大小,应该考虑使用傅立叶变换算法进行相关性。如果您对此感兴趣,请查看该库的示例(免责声明:我编写了该库,它仅依赖于NumPy)

以下是NumPy代码(我为测试而编写)的计时、代码向量的自动相关和tidynamics,仅供参考

size = [2**i for i in range(4, 17, 2)]

np_time = []
ti_time = []
va_time = []
for s in size:
    data = np.random.random(size=(s, 3))
    t0 = time.time()
    correlate = np.array([np.correlate(data[:,i], data[:,i], mode='full') for i in range(data.shape[1])])[:,:s]
    correlate = np.sum(correlate, axis=0)/(s-np.arange(s))
    np_time.append(time.time()-t0)
    t0 = time.time()
    correlate = tidynamics.acf(data)
    ti_time.append(time.time()-t0)
    t0 = time.time()
    correlate = vector_autocorrelate(data)
    va_time.append(time.time()-t0)
您可以看到以下结果:

print("size", size)
print("np_time", np_time)
print("va_time", va_time)
print("ti_time", ti_time)
大小[16,64,256,1024,4096,1638465536]

np_时间[0.00023794174194335938,0.0002703666687011719,0.0002713203430175781, 0.001544952392578125、0.0278470516204834、0.36094141006469727、6.922360420227051]

弗吉尼亚大学时间[0.00021696090698242188,0.0001690387725830078,0.00033950805664625,0.0014629364013671875,0.0249309593979492188,0.34442687034606934,7.00563073182642]

ti_时间[0.0011148452758789062,0.0008449554443359375,0.0007512569427490234,, 0.00104880332946777734、0.0026645660400390625、0.007939338684082031、0.048232316970825195]

或者策划它们

plt.plot(size, np_time)
plt.plot(size, va_time)
plt.plot(size, ti_time)
plt.loglog()

对于非常小的数据序列以外的任何数据序列,“N**2”算法都不可用。

NumPy例程适用于1D数组。作为“最小”改进,对规范化步骤使用矢量化操作(使用前一行到最后一行中的
np.arange
):

对于较大的数组大小,应该考虑使用傅立叶变换算法进行相关性。如果您对此感兴趣,请查看该库的示例(免责声明:我编写了该库,它仅依赖于NumPy)

以下是NumPy代码(我为测试而编写)的计时、代码向量的自动相关和tidynamics,仅供参考

size = [2**i for i in range(4, 17, 2)]

np_time = []
ti_time = []
va_time = []
for s in size:
    data = np.random.random(size=(s, 3))
    t0 = time.time()
    correlate = np.array([np.correlate(data[:,i], data[:,i], mode='full') for i in range(data.shape[1])])[:,:s]
    correlate = np.sum(correlate, axis=0)/(s-np.arange(s))
    np_time.append(time.time()-t0)
    t0 = time.time()
    correlate = tidynamics.acf(data)
    ti_time.append(time.time()-t0)
    t0 = time.time()
    correlate = vector_autocorrelate(data)
    va_time.append(time.time()-t0)
您可以看到以下结果:

print("size", size)
print("np_time", np_time)
print("va_time", va_time)
print("ti_time", ti_time)
大小[16,64,256,1024,4096,1638465536]

np_时间[0.00023794174194335938,0.0002703666687011719,0.0002713203430175781, 0.001544952392578125、0.0278470516204834、0.36094141006469727、6.922360420227051]

弗吉尼亚大学时间[0.00021696090698242188,0.0001690387725830078,0.00033950805664625,0.0014629364013671875,0.0249309593979492188,0.34442687034606934,7.00563073182642]

ti_时间[0.0011148452758789062,0.0008449554443359375,0.0007512569427490234,, 0.00104880332946777734、0.0026645660400390625、0.007939338684082031、0.048232316970825195]

或者策划它们

plt.plot(size, np_time)
plt.plot(size, va_time)
plt.plot(size, ti_time)
plt.loglog()

对于非常小的数据序列以外的任何数据序列,“N**2”算法都无法使用。

以下是我的结果。它速度较慢(约为4倍),并提供其他结果。我为什么要发呢?我认为值得一看如何测量以及两者之间的区别。此外,如果有人找到不同结果的原因,我会更高兴

因此,以下是我的解决方案:

%timeit [np.mean([np.dot(a[t], a[i+t]) for i in range(len(a)-t)]) for t in range(len(a))]
结果:每个循环95.2µs±3.41µs(7次循环的平均值±标准偏差,每个循环10000次)

相比之下,您的解决方案大约快4倍:

%timeit vector_autocorrelate(a)

提供:每个循环24.8µs±1.46µs(7次运行的平均值±标准偏差,每个循环10000次)

以下是我的结果。它速度较慢(约为4倍),并提供其他结果。我为什么要发呢?我认为值得一看如何测量以及两者之间的区别。此外,如果有人找到不同结果的原因,我会更高兴

因此,以下是我的解决方案:

%timeit [np.mean([np.dot(a[t], a[i+t]) for i in range(len(a)-t)]) for t in range(len(a))]
结果:每个循环95.2µs±3.41µs(7次循环的平均值±标准偏差,每个循环10000次)

相比之下,您的解决方案大约快4倍:

%timeit vector_autocorrelate(a)

提供:每个循环24.8µs±1.46µs(7次运行的平均值±标准偏差,每个循环10000次)

Hi I面临类似问题。这是我的想法

def fast_vector_correlation(M):
    n_row = M.shape[0]
    dot_mat = M.dot(M.T)
    corr = [np.trace(dot_mat,offset=x) for x in range(n_row)]
    corr/=(n_row-np.arange(n_row))
    return corr

其思想是,
dot\u mat
包含行向量之间的所有标量积。要计算不同
t
值下的相关性,您只需将对角线(右上角的三角形部分)相加,如图所示。

Hi我遇到了一个类似的问题。这是我的想法

def fast_vector_correlation(M):
    n_row = M.shape[0]
    dot_mat = M.dot(M.T)
    corr = [np.trace(dot_mat,offset=x) for x in range(n_row)]
    corr/=(n_row-np.arange(n_row))
    return corr

其思想是,
dot\u mat
包含行向量之间的所有标量积。要计算不同
t
值下的相关性,只需将对角线(右上角三角形部分)相加即可,如图所示。

一如往常,我很高兴听到downv的原因