如何从 python/scipy/numpy 等中的阶跃函数中采样?
How to sample from a step function in python/scipy/numpy etc?
如果我有 bin 边缘和每个 bin 的计数,是否有一种简洁的方法可以从这意味着从概率密度函数中抽样?
这是我的意思的一个例子。
bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]
概率密度函数是阶跃函数,步长为:
[0,2.1,6.3,23.5]
第一步的概率密度(台阶高度)为5/(17*2.1)。
第二个bin/step的概率密度是2/(17*4.2),第三个step/bin的概率密度是10/(17*17.2)。
如果您落在 bin/step 中,您采样的值是从步骤的 x 值中统一采样的。因此,如果您在第一步中跌倒,则它在 0 和 2.1 之间是统一的。
是否有使用 Python 模块执行此采样的简洁方法?例如使用 scipy/numpy/etc?
您已经给出了答案:
If you fall in a bin/step the value you sample is uniformly sampled from the x-values of the step. So if you fall in the first step it is uniform between 0 and 2.1.
您以 two-step 方式生成示例:
- 根据概率质量函数选择一个 bin
- 生成在所选 bin 的值范围内均匀分布的样本
下面的函数就是这样做的
def random_sample(bin_edges, counts):
n_bins = len(counts) # number of bins
p_bin = counts/np.sum(counts) # probability mass function (pmf) for the bin
sample_bin = np.random.choice(np.arange(n_bins), p = p_bin) # sample a bin according to the bin pmf
# now, generate a random variable uniformly distributed within the sampled bin edges
sample = np.random.uniform(bin_edges[sample_bin], bin_edges[sample_bin + 1])
return sample
为了测试函数,让我们生成多个独立样本并绘制它们的直方图
bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]
samples = [random_sample(bin_edges, counts) for _ in range(100000)]
from seaborn import distplot
distplot(samples,bins = 100,kde=False,norm_hist = True, hist_kws=dict(edgecolor="k", linewidth=1))
不出所料,直方图对应随机变量的分布函数
"If I have bin edges and counts for each bin, is there a nice succinct way to sample from the probability density function this implies?"
这正是 scipy.stats.rv_histogram
的情况。
这是一个例子。
首先,生成一些我们可以用于示例的直方图数据。
In [150]: sample = np.random.gamma(6, size=2000)
In [151]: hist, edges = np.histogram(sample, bins=5)
In [152]: hist
Out[152]: array([490, 949, 438, 100, 23])
In [153]: edges
Out[153]:
array([ 1.23006474, 4.19769156, 7.16531838, 10.13294519, 13.10057201,
16.06819883])
使用该数据创建 rv_histogram
的实例。
In [154]: from scipy.stats import rv_histogram
In [155]: rv = rv_histogram((hist, edges))
从 rv
生成随机样本,并绘制其直方图。
In [156]: rv_sample = rv.rvs(size=100000)
In [157]: plt.hist(rv_sample, bins=50, alpha=0.5, edgecolor='k')
如果我有 bin 边缘和每个 bin 的计数,是否有一种简洁的方法可以从这意味着从概率密度函数中抽样?
这是我的意思的一个例子。
bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]
概率密度函数是阶跃函数,步长为:
[0,2.1,6.3,23.5]
第一步的概率密度(台阶高度)为5/(17*2.1)。 第二个bin/step的概率密度是2/(17*4.2),第三个step/bin的概率密度是10/(17*17.2)。
如果您落在 bin/step 中,您采样的值是从步骤的 x 值中统一采样的。因此,如果您在第一步中跌倒,则它在 0 和 2.1 之间是统一的。
是否有使用 Python 模块执行此采样的简洁方法?例如使用 scipy/numpy/etc?
您已经给出了答案:
If you fall in a bin/step the value you sample is uniformly sampled from the x-values of the step. So if you fall in the first step it is uniform between 0 and 2.1.
您以 two-step 方式生成示例:
- 根据概率质量函数选择一个 bin
- 生成在所选 bin 的值范围内均匀分布的样本
下面的函数就是这样做的
def random_sample(bin_edges, counts):
n_bins = len(counts) # number of bins
p_bin = counts/np.sum(counts) # probability mass function (pmf) for the bin
sample_bin = np.random.choice(np.arange(n_bins), p = p_bin) # sample a bin according to the bin pmf
# now, generate a random variable uniformly distributed within the sampled bin edges
sample = np.random.uniform(bin_edges[sample_bin], bin_edges[sample_bin + 1])
return sample
为了测试函数,让我们生成多个独立样本并绘制它们的直方图
bin_edges = [0,2.1,6.3,23.5]
counts = [5,2,10]
samples = [random_sample(bin_edges, counts) for _ in range(100000)]
from seaborn import distplot
distplot(samples,bins = 100,kde=False,norm_hist = True, hist_kws=dict(edgecolor="k", linewidth=1))
不出所料,直方图对应随机变量的分布函数
"If I have bin edges and counts for each bin, is there a nice succinct way to sample from the probability density function this implies?"
这正是 scipy.stats.rv_histogram
的情况。
这是一个例子。
首先,生成一些我们可以用于示例的直方图数据。
In [150]: sample = np.random.gamma(6, size=2000)
In [151]: hist, edges = np.histogram(sample, bins=5)
In [152]: hist
Out[152]: array([490, 949, 438, 100, 23])
In [153]: edges
Out[153]:
array([ 1.23006474, 4.19769156, 7.16531838, 10.13294519, 13.10057201,
16.06819883])
使用该数据创建 rv_histogram
的实例。
In [154]: from scipy.stats import rv_histogram
In [155]: rv = rv_histogram((hist, edges))
从 rv
生成随机样本,并绘制其直方图。
In [156]: rv_sample = rv.rvs(size=100000)
In [157]: plt.hist(rv_sample, bins=50, alpha=0.5, edgecolor='k')