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

时间:2016-11-01 16:51:26

标签: python algorithm performance numpy matrix

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

<?php
/**
 * @var \Zend\Form\Element\Radio $element
 */

$element_options = $element->getValueOptions();
$element_attributes = $element->getAttributes();
$element_value = $element->getValue();
?>
<fieldset>
    <legend><?php echo $element->getLabel(); ?> * </legend>
    <?php foreach($element_options as $key => $value) { ?>

    <label class="col-md-12">
        <input type="radio" value="<?php echo $value['value']; ?>" class="field-foo" name="<?php echo $element_attributes['name']; ?>[]"><?php echo $value['value']; ?>
    </label>
    <?php } ?>
</fieldset>

我应该如何更改此代码以使其更快?

Shapes: X.shape = mask.shape = logBN.shape = (500,500,1000), 
        F.shape = (20,20), 
        A.shape = (481,481), 
        s2 -- scalar.

2 个答案:

答案 0 :(得分:1)

在对logexppower的代数操作进行大量处理之后,一切都来到了这一点 -

# 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]标量划分不会有效,所以用倒数乘以乘法。因此,作为预处理存储它们在进入循环之前的倒数。

答案 1 :(得分:0)

试图理解你的内循环

    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

因此idxmaskA中定义了一个子数组。您在阵列外使用logBN;并在其中term。您在第1个2 dim上对值进行求和,因此term1term2的形状X.shape[2]都保存在q中。

那个面具/窗口是20x20。

作为第一次剪辑,我尝试同时为所有term2i计算j。这看起来像是典型的滑动窗口问题。我还尝试将term1表示为减法 - 整个logBN减去此窗口。