我试图为我的学生作业编写一个算法,它运作良好。但是,计算需要很长时间,特别是对于大型阵列。 这部分代码正在减慢所有程序。
<?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.
答案 0 :(得分:1)
在对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]标量划分不会有效,所以用倒数乘以乘法。因此,作为预处理存储它们在进入循环之前的倒数。
答案 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
因此idx
和mask
在A
中定义了一个子数组。您在阵列外使用logBN
;并在其中term
。您在第1个2 dim上对值进行求和,因此term1
和term2
的形状X.shape[2]
都保存在q
中。
那个面具/窗口是20x20。
作为第一次剪辑,我尝试同时为所有term2
,i
计算j
。这看起来像是典型的滑动窗口问题。我还尝试将term1
表示为减法 - 整个logBN
减去此窗口。