【问题标题】:Drawing random data from a given two dimensional distribution function [closed]从给定的二维分布函数中提取随机数据
【发布时间】:2014-06-16 14:22:02
【问题描述】:

我有一个理论分布,我想在二维空间中随机抽样得到以下分布:

def p(z,m):
    E = { 'ft':0.55, 'alpha': 2.99, 'z0':0.191, 'km':0.089, 'kt':0.25 }
    S = { 'ft':0.39, 'alpha': 2.15, 'z0':0.121, 'km':0.093, 'kt':-0.175 }
    I={ 'ft':0.06, 'alpha': 1.77, 'z0':0.045, 'km':0.096, 'kt':0.0 }
    Evalue=E['ft']*np.exp(-1*E['kt']*(m-20))*z**E['alpha']*np.exp(-1*(z/(E['z0']+E['km']*(m-20)))**E['alpha'])
    Svalue=S['ft']*np.exp(-1*S['kt']*(m-20))*z**S['alpha']*np.exp(-1*(z/(S['z0']+S['km']*(m-20)))**S['alpha'])
    Ivalue=I['ft']*np.exp(-1*I['kt']*(m-20))*z**I['alpha']*np.exp(-1*(z/(I['z0']+I['km']*(m-20)))**I['alpha'])
    value=Evalue+Svalue+Ivalue
    return value

更新: 我发现逆变换采样是从概率分布中采样数据的合适方法。 我如何在 python 中为 2D 数据编写此方法,或者我可以使用任何库?

【问题讨论】:

  • 如果你没有大的速度限制,最简单的事情就是使用拒绝方法。

标签: numpy scipy probability static-methods probability-theory


【解决方案1】:

看看马尔可夫链蒙特卡罗 (MCMC) 方法。基本上你在 (z, m) 点的空间中跳跃。无论你在哪里,你总是接受增加 p(z, m) 的跳跃。你接受一个以一定概率减小 p(z, m) 的跳跃。有一个 Python 库 PyMC 可以执行该过程。

【讨论】:

  • 在 2D 中像 inverse transform sampling 这样的东西怎么样,但问题是如何为复杂的 2D 分布制作逆 CDF
  • 不,逆变换采样不能直接应用于多于一维。您可以构造 p(m | z) 和 p(z) 并首先从 p(z) 采样,然后通过逆变换方法从 p(m | z) 采样,但这是不必要的复杂化。最好直接通过 MCMC 解决问题。
  • 或者只是编码Metropolis-Hastings algorithm,这非常简单。
【解决方案2】:

如果您想从 p(z,m) 中随机抽取一个值,那么实现此目的的一种简单方法是使用 python 中的“随机”模块。我使用 numpy 的 random 版本来展示这个想法:

import numpy as np
import matplotlib.pyplot as plt

def p(z,m):
    E = { 'ft':0.55, 'alpha': 2.99, 'z0':0.191, 'km':0.089, 'kt':0.25 }
    S = { 'ft':0.39, 'alpha': 2.15, 'z0':0.121, 'km':0.093, 'kt':-0.175 }
    I={ 'ft':0.06, 'alpha': 1.77, 'z0':0.045, 'km':0.096, 'kt':0.0 }
    Evalue=E['ft']*np.exp(-1*E['kt']*(m-20))*z**E['alpha']*np.exp(-1*(z/(E['z0']+E['km']*(m-20)))**E['alpha'])
    Svalue=S['ft']*np.exp(-1*S['kt']*(m-20))*z**S['alpha']*np.exp(-1*(z/(S['z0']+S['km']*(m-20)))**S['alpha'])
    Ivalue=I['ft']*np.exp(-1*I['kt']*(m-20))*z**I['alpha']*np.exp(-1*(z/(I['z0']+I['km']*(m-20)))**I['alpha'])
    value=Evalue+Svalue+Ivalue
    return value

# Define the number of iterations you want for each variable    
num_iter_m = 50
num_iter_z = 50

# I then set rand_m to go from 20 to 30, as your function fails for <20
rand_m = (np.random.random(num_iter_m)*10)+20

# z goes from the range 0 - 1
rand_z = (np.random.random(num_iter_z))

# Note, I am sampling from a uniform distribution for m and z. You can use more complicated functions, i.e., Gaussian/Normal shapes or even user defined.

rand_p = np.zeros((len(rand_z), len(rand_m)))

# Fill a grid with the random p(z,m) values
for i in range(len(rand_z)):
  for j in range(len(rand_m)):
    rand_p[i][j] = p(rand_z[i], rand_m[j])

# Plot
fig = plt.figure(0)

ax1 = fig.add_subplot(211)
ax1.scatter(rand_z, rand_m)
ax1.set_xlabel("z")
ax1.set_ylabel("m")

ax2 = fig.add_subplot(212)
cf = ax2.contourf(rand_z, rand_m, rand_p)
ax2.set_xlabel("z")
ax2.set_ylabel("m")

colbar = plt.colorbar(cf)
colbar.set_label("p(z,m)")

plt.show()

以更复杂的方式使用它的特定模块将是,例如 PyMC ( https://github.com/pymc-devs/pymc) 或司仪 (http://dan.iel.fm/emcee/current/)。

如果您想通过二维函数 p(z,m) 对 z 和 m 进行加权采样,这会稍微复杂一些。

【讨论】:

  • 这似乎不是解决 OP 提出的问题的方法。 “如果你想对二维函数 p(z,m) 加权的 z 和 m 进行采样”——我很确定这就是他想要的。
猜你喜欢
  • 2021-04-16
  • 1970-01-01
  • 2019-09-24
  • 2021-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多