有效地找到稀疏函数的总和

时间:2017-07-22 02:11:47

标签: python performance numpy vectorization

我有一个统计情况,我想找到一些极其尖锐的函数的总和。也就是说,给定一组输入点in和输出点out,我想找到数字sum_in f(in,out),其中f非常尖锐。

具体情况可能是这样的情况:

import numpy as np

sample_pts = 10 ** 7
data_pts = 10 ** 5

mu = np.random.rand(data_pts)
x = np.linspace(0, 1, sample_pts)

def f(mu, x): 
    return np.exp(-1e10 * ((mu - x) ** 2))

我目前的解决方案是迭代采样点,对数据点进行矢量化:

results = np.zeros(sample_pts)
for i in range(sample_pts):
    results[i] = np.sum(f(mu, x[i]))

然而,这是非常低效的,因为这里计算的绝大多数数字都非常小 - 实际上,许多在浮点精度范围内为零!这里应该有足够的空间来加速至少一千倍。

假设一些小的数字误差(比如十亿分之一)是可以接受的,那么在numpy中计算这个总和的最快方法是什么?

1 个答案:

答案 0 :(得分:0)

使用此功能,您不需要迭代

In [833]: mu = np.random.rand(10)
In [834]: x = np.linspace(0,1,6)
In [836]: def f(mu, x): 
     ...:     return np.exp(.1* ((mu - x) ** 2))
     ...: 
In [837]: f(mu, np.arange(10))   # same shape
Out[837]: 
array([  1.00005667e+00,   1.00151080e+00,   1.33174582e+00,
         2.27563858e+00,   3.14399507e+00,   9.37132782e+00,
         1.53439871e+01,   6.54667741e+01,   4.85267134e+02,
         3.11160087e+03])
In [838]: f(mu, x[:,None])   # 'outer' broadcasting
Out[838]: 
array([[ 1.00005667,  1.079973  ,  1.00949403,  1.00175693,  1.03860883,
         1.00729568,  1.06179883,  1.0288728 ,  1.00184352,  1.00010102],
       [ 1.00310927,  1.04691816,  1.00115406,  1.00045585,  1.01741263,
         1.00048473,  1.03353998,  1.01118532,  1.00041336,  1.00283372],
       [ 1.01425284,  1.0230266 ,  1.00085791,  1.00718177,  1.00465417,
         1.00170149,  1.01411376,  1.00178422,  1.00700916,  1.01365075],
       [ 1.03375727,  1.00770978,  1.00859845,  1.02209706,  1.00002398,
         1.01097526,  1.00304502,  1.00044212,  1.02179017,  1.032814  ],
       [ 1.06209967,  1.00059511,  1.02456265,  1.04556437,  1.00341039,
         1.0285303 ,  1.00006571,  1.0071267 ,  1.0451157 ,  1.06079202],
       [ 1.0999839 ,  1.0015108 ,  1.04913917,  1.07816138,  1.01489503,
         1.05479487,  1.00510399,  1.02199931,  1.0775598 ,  1.09827913]])

和总和

In [839]: _.sum(axis=1)
Out[839]: 
array([ 10.22980131,  10.11750708,  10.08823266,  10.1412531 ,
        10.27786262,  10.50142738])

我改变了常数;使用-1e10所有术语0(具有公差)。

我不知道压缩计算的方法,除了消除已知会产生非常小的结果的mux的值。

使用-1e10参数时,我必须给它x非常接近mu以获得非零值:

In [857]: f(mu, mu-.0001).sum()
Out[857]: 3.7200759760847501e-43