python - 根据两种不同的分布生成一个样本
问题描述
我想在[0;1000]
size 的区间内随机生成一个样本1E4
。但遵循两种不同的分布:一种在[0;1]
间隔中遵循递增的指数分布,这将产生一个接近于1
其他接近的值的基准0
。[1;1000]
然后,在分布之后的间隔中生成我的样本的第二部分1/r
。
我认为更简单的方法是将全局样本分成两个不同的样本。但我不知道如何处理它。我试图使用图书馆的一些分布,scipy
但我没有找到一种方法来正确使用它们来生成我的全局样本。你怎么看?
解决方案
您可以使用两个单独的分布,但您需要确保样本数在边界点 ( r == 1
) 处匹配。因此,您需要估计左 (exp) 和右 (1/r) 分布所需的样本数。两个分布的积分如下:
- 将 exp(r) 从 0 积分到 1:
exp(1) - 1 == 1.7183
- 将 1/r 从 1 积分到 1000:
log(1000) == 6.9078
这意味着左分布的概率r = 1
是exp(1) / 1.7183
,而右分布的概率是1 / 6.9078
。所以这给出了一个比率ratio = left / right = 10.928
。这意味着您需要ratio
在右侧间隔中生成比左侧多倍的值,以便最终在边界处获得相同数量的样本。假设您想N
总共生成样本,这意味着您需要N1 = N / (ratio + 1)
在左侧 (exp) 间隔中生成样本,N2 = N * ratio / (ratio + 1)
在右侧 (1/r) 区间中生成样本。
所以这里有一些示例代码:
import matplotlib.pyplot as plt
import numpy as np
r_max = 1000.0
integral_1 = np.exp(1.0) - 1.0 # 1.7183
integral_2 = np.log(r_max) # 6.9078
N = 2_000_000 # total number of samples
ratio = np.exp(1.0) / integral_1 * integral_2 # 10.928
N1 = int(N / (ratio + 1))
N2 = int(N * ratio / (ratio + 1))
# Use inverse transform sampling in the following.
s1 = np.log(integral_1 * np.random.random(size=N1) + 1.0)
s2 = np.exp(integral_2 * np.random.random(size=N2))
samples = np.concatenate((s1, s2))
np.random.shuffle(samples) # optionally shuffle the samples
plt.hist(samples, bins=int(20 * r_max))
plt.xlim([0, 5])
plt.show()
产生以下分布:
推荐阅读
- python - 如何使此函数中的代码重复?(Python)
- python - atexit._run_exitfuncs 中的 Python concurrent.futures 错误:OSError:句柄已关闭,仅在 Visual Studio 调试模式下运行
- python - 将列表转换为字符串?
- python - 在字符前提取单词
- android - android,FCM如何知道令牌应该发送的时间和对象
- php - 多维数组按对象推送无法正常工作
- google-apps-script - 使用 Google Chat API 和 Google Apps Scripts 制作类似于 Slack 的消息提醒
- azure-devops - 在 YAML 中具有多个放置文件夹的 Azure Pipeline
- import - 来自 Web 动态 DAX 的 Power Query
- sql - 转换为 ActiveRecord 查询(火鸟数据库)时导致错误的原始 SQL 查询