我有一个统计情况,我想找到一些极其尖锐的函数的总和。也就是说,给定一组输入点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中计算这个总和的最快方法是什么?
答案 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(具有公差)。
我不知道压缩计算的方法,除了消除已知会产生非常小的结果的mu
和x
的值。
使用-1e10参数时,我必须给它x
非常接近mu
以获得非零值:
In [857]: f(mu, mu-.0001).sum()
Out[857]: 3.7200759760847501e-43