我有两个时间序列A和B. A的长度为m
,B的长度为n
。 m << n
。两者都具有维度d
。
我通过在B上滑动A来计算A与B中所有子序列之间的距离。 在python中,代码看起来像这样。
def sliding_dist(A,B)
n = len(B)
dist = np.zeros(n)
for i in range(n-m):
subrange = B[i:i+m,:]
distance = np.linalg.norm(A-subrange)
dist[i] = distance
return dist
现在这段代码需要花费大量时间来执行,而且我还有很多计算要做。 我需要加快计算速度。我的猜测是我可以通过使用卷积和频域乘法(FFT)来实现这一点。但是,我一直无法实现它。
有什么想法吗? :)谢谢
答案 0 :(得分:4)
norm(A - subrange)
本身不是卷积,但可以表示为:
sqrt(dot(A, A) + dot(subrange, subrange) - 2 * dot(A, subrange))
如何快速计算每个词:
dot(A, A)
- 这只是一个常数。
dot(subrange, subrange)
- 这可以使用递归方法在O(1)(每个位置)中计算。
dot(A, subrange)
- 此 是此上下文中的卷积。所以这可以通过convolution theorem在频域中计算。 1
但请注意,如果子范围大小仅为10,则不太可能看到性能提升。
<子> 1。 AKA fast convolution。
答案 1 :(得分:1)
使用矩阵操作实现,就像我在评论中提到的那样。想法是逐步评估规范。在你的情况下,我的价值是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print(char *a[]);
void arr_sort( char *a[]);
int main()
{
int i;
char *array[8];
printf("Please input a string with size 7:");
for(i=0;i<7;i++)
{
scanf("%s",array);
}
printf("the array before sorting is");
print(array);
arr_sort(array);
print(array);
return 0;
}
void arr_sort( char *a[])
{
int i,j;
char *temp;
for(i=0;i<7;i++)
{
for(j=0;j<7;j++)
{
if(strcmp(a[j],a[j+1])>0)
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
void print(char *a[])
{
int i;
for(i=0;i<7;i++)
{
printf("%s ",a[i]);
}
}
前三行计算平方和,最后一行是sqrt()。
加速大约是60倍。
d[i] = sqrt((A[0] - B[i])^2 + (A[1] - B[+1])^2 + ... + (A[m-1] - B[i+m-1])^2)
<强>更新强>
这是在矩阵运算中需要的“重新实现”规范。如果您想要numpy提供的其他规范,则不灵活。由于norm()接收参数轴,因此可以使用不同的方法来创建B滑动窗口的矩阵并在整个数组上制定规范。这是该方法的实现,但加速速度约为40x,比以前慢。
import numpy
import time
def sliding_dist(A, B):
m = len(A)
n = len(B)
dist = numpy.zeros(n-m)
for i in range(n-m):
subrange = B[i:i+m]
distance = numpy.linalg.norm(A-subrange)
dist[i] = distance
return dist
def sd_2(A, B):
m = len(A)
dist = numpy.square(A[0] - B[:-m])
for i in range(1, m):
dist += numpy.square(A[i] - B[i:-m+i])
return numpy.sqrt(dist, out=dist)
A = numpy.random.rand(10)
B = numpy.random.rand(500)
x = 1000
t = time.time()
for _ in range(x):
d1 = sliding_dist(A, B)
t1 = time.time()
for _ in range(x):
d2 = sd_2(A, B)
t2 = time.time()
print numpy.allclose(d1, d2)
print 'Orig %0.3f ms, second approach %0.3f ms' % ((t1 - t) * 1000., (t2 - t1) * 1000.)
print 'Speedup ', (t1 - t) / (t2 - t1)