2016-04-30 37 views
9

我有以下两个功能:不同的结果与量化代码标准循环中numpy的

def loop(x): 
    a = np.zeros(10) 
    for i1 in range(10): 
     for i2 in range(10): 
      a[i1] += np.sin(x[i2] - x[i1]) 
    return a 

def vectorized(x):  
    b = np.zeros(10) 
    for i1 in range(10): 
     b += np.sin(np.roll(x, i1) - x) 
    return b 

然而,当我运行这两个,我发现他们的结果略有不同:

x = np.arange(10) 
a, b = loop(x), vectorized(x) 
print b - a 

我得到:

[ 2.22044605e-16 0.00000000e+00 0.00000000e+00 6.66133815e-16 
    -2.22044605e-16 2.22044605e-16 0.00000000e+00 2.22044605e-16 
    2.22044605e-16 2.22044605e-16] 

这是非常小的,但在我的情况下,影响模拟。如果我从函数中删除np.sin,则差异消失。或者,如果对x使用np.float32,差异也会消失,但这是由使用float64的解算器解决的颂歌的一部分。有没有办法解决这种差异?

+10

不幸的是,当你重新排序操作,比如你做了,就很难(不可能?)尽量将差别从舍入误差的量级进入。如果这实际上在最终解决方案中存在显着差异,那么您需要开始问自己,如果您需要选择不太敏感的ODE解算器(或者您尝试解决的系统展现混沌行为,这使得某些类型的建模不可能) – mgilson

回答

6

这是因为您没有按照相同的顺序进行操作。

对于等效的完全向量化解决方案,请执行c=sin(add.outer(x,-x))).sum(axis=0)

In [8]: (c==loop(x)).all() 
Out[8]: True 

与您共赢矢量化的全爱维稳特:

In [9]: %timeit loop(x) 
1000 loops, best of 3: 750 µs per loop 

In [10]: %timeit vectorized(x) 
1000 loops, best of 3: 347 µs per loop 

In [11]: %timeit sin(x[:,None]-x).sum(axis=0) 
10000 loops, best of 3: 46 µs per loop