Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 加速矩阵计算(在子阵列上循环)[numpy]_Python_Algorithm_Performance_Numpy_Matrix - Fatal编程技术网

Python 加速矩阵计算(在子阵列上循环)[numpy]

Python 加速矩阵计算(在子阵列上循环)[numpy],python,algorithm,performance,numpy,matrix,Python,Algorithm,Performance,Numpy,Matrix,我正试图为我的学生作业编写一个算法,它运行良好。但是,计算需要很长时间,特别是对于大型阵列。 这部分代码正在减慢所有程序的速度 Shapes: X.shape = mask.shape = logBN.shape = (500,500,1000), F.shape = (20,20), A.shape = (481,481), s2 -- scalar. 我应该如何更改此代码以使其更快 h = F.shape[0] w = F.shape[

我正试图为我的学生作业编写一个算法,它运行良好。但是,计算需要很长时间,特别是对于大型阵列。 这部分代码正在减慢所有程序的速度

Shapes: X.shape = mask.shape = logBN.shape = (500,500,1000), 
        F.shape = (20,20), 
        A.shape = (481,481), 
        s2 -- scalar.
我应该如何更改此代码以使其更快

h = F.shape[0]
w = F.shape[1]
q = np.zeros((A.shape[0], A.shape[1], X.shape[2]))
for i in range(A.shape[0]):
    for j in range(A.shape[1]):
        mask[:,:,:] = 0
        mask[i:i + h,j:j + w,:] = 1
        q[i,j,:] = ((logBN*(1 - mask)).sum(axis=(0,1)) + 
                    (np.log(norm._pdf((X[i:i + h,j:j + w,:]-F[:,:,np.newaxis])/s2)/s2)).sum(axis=(0,1))

只是想弄清楚你的内心循环

    mask[:,:,:] = 0
    mask[i:i + h,j:j + w,:] = 1
    q[i,j,:] = ((logBN*(1 - mask)).sum(axis=(0,1)) + 
                (np.log(norm._pdf((X[i:i + h,j:j + w,:]-F[:,:,np.newaxis])/s2)/s2)).sum(axis=(0,1))
看起来像

idx = (slice(i,i+h), slice(j,j_w), slice(None))
mask = np.zeros(X.shape)
mask(idx) = 1
mask = 1 - mask 
# alt mask=np.ones(X.shape);mask[idx]=0
term1 = (logBN*mask).sum(axis=(0,1))
term2 = np.log(norm._pdf((X[idx] - F[...,None])/s2)/s2).sum(axis=(0,1))
q[i,j,:] = term1 + term2
因此,
idx
mask
a
中定义子阵列。您正在阵列外部使用
logBN
;和
术语
。您正在对前2个dim上的值求和,因此
term1
term2
都具有形状
X.shape[2]
,您将其保存在
q

那个遮罩/窗口是20x20


作为第一个切入点,我将尝试一次计算所有
I
j
term2
。这看起来像是一个典型的滑动窗口问题。我还尝试将
术语1
表示为一个减法-整个
logBN
减去这个窗口。

通过
log
exp
power
的代数运算进行繁重的杂耍之后,一切都变成了这样-

# Params
m,n = F.shape[:2]
k1 = 1.0/(s2*np.sqrt(2*np.pi))
k2 = -0.5/s2**2
k3 = np.log(k1)*m*n

out = np.zeros((A.shape[0], A.shape[1], X.shape[2]))
for i in range(A.shape[0]):
    for j in range(A.shape[1]):
        mask[:] = 1
        mask[i:i + h,j:j + w,:] = 0
        XF = (X[i:i + h,j:j + w,:]-F[:,:,np.newaxis])        
        p1 = np.einsum('ijk,ijk->k',logBN,mask)
        p2 = k2*np.einsum('ijk,ijk->k',XF,XF)
        out[i,j,:] = p1 + p2
out += k3
使用的东西很少-

1] norm.pdf基本上是:
norm.pdf(x)=exp(-x**2/2)/sqrt(2*pi)
。因此,我们可以内联实现并在脚本级别优化这些实现


2] 用标量除法效率不高,所以用倒数乘法代替了标量除法。因此,作为一种预处理,在进入循环之前存储它们的倒数。

这还不完整-将所有变量(F、a、X)都放进去,这样人们就可以处理一些事情了。如果对数组进行迭代,通常最好将其转换为python列表,因为它非常慢-最快的是使用向量运算。@kabanus我不能确定它们是在程序工作期间生成的。我建议打印一次,将结果粘贴在这里。@Divakar我刚刚添加了信息:logBN——矩阵和s2——标量。这就是栅格!非常感谢。我想更改一个算法,但您使用
einsum
的解决方案的速度要快8倍。虽然我不明白为什么它比普通的numpy函数运行得更快。@Acapello相信我,我不得不仔细研究代数函数,因此在文章顶部有这样的评论。这是一次令人精疲力尽的会议!:)这是更快的,因为我们所做的操作要少得多。