【发布时间】:2018-03-10 16:01:46
【问题描述】:
我想从 Python 中的任意函数中采样。
Fast arbitrary distribution random sampling 中提到可以使用逆变换采样,Pythonic way to select list elements with different probability 中提到应该使用逆累积分布函数。据我所知,这些方法仅适用于单变量情况。我的函数是多变量的,而且过于复杂,https://stackoverflow.com/a/48676209/4533188 中的任何建议都适用。
原理:我的函数是基于Rosenbrock的香蕉函数,我们可以用哪个值得到函数的值
import scipy.optimize
scipy.optimize.rosen([1.1,1.2])
(这里[1.1,1.2]是输入向量)来自scipy,见https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.optimize.rosen.html。
这是我想出的:我在我感兴趣的区域上制作了一个网格,并为每个点计算函数值。然后我按值对结果数据框进行排序并进行累积和。通过这种方式,我们得到了具有不同大小的“槽”——具有大函数值的点比具有小函数值的点具有更大的槽。现在我们生成随机值并查看随机值落入哪个槽。数据框的行是我们的最终样本。
代码如下:
import scipy.optimize
from itertools import product
from dfply import *
nb_of_samples = 50
nb_of_grid_points = 30
rosen_data = pd.DataFrame(array([item for item in product(*[linspace(fm[0], fm[1], nb_of_grid_points) for fm in zip([-2,-2], [2,2])])]), columns=['x','y'])
rosen_data['z'] = [np.exp(-scipy.optimize.rosen(row)**2/500) for index, row in rosen_data.iterrows()]
rosen_data = rosen_data >> \
arrange(X.z) >> \
mutate(z_upperbound=cumsum(X.z)) >> \
mutate(z_upperbound=X.z_upperbound/np.max(X.z_upperbound))
value = np.random.sample(1)[0]
def get_rosen_sample(value):
return (rosen_data >> mask(X.z_upperbound >= value) >> select(X.x, X.y)).iloc[0,]
values = pd.DataFrame([get_rosen_sample(s) for s in np.random.sample(nb_of_samples)])
这很好用,但我认为它不是很有效。什么是对我的问题更有效的解决方案?
我读到马尔可夫链 Monte Carlo 可能会有所帮助,但现在我想知道如何在 Python 中做到这一点。
【问题讨论】:
标签: python distribution sampling