python - 如何对具有不同分布的少数数字进行抽样?
问题描述
假设我有自己的自定义分发 numpy 向量,称为p
.
那么p
满足以下条件:
np.ndim(p) == 1 & np.sum(p) == 1 & np.all(p >= 0)
使用该向量,我可以轻松地采样一个[0, p.shape)
数字np.random.choice(np.arange(len(p)), p=p)
在我有很多这样p
的 s 的情况下,我有一个矩阵(暗 2)P
满足:
np.sum(P[:,i]) == 1 # for all i in P.shape[1]
np.all(P >= 0)
然后我希望以概率 PP.shape[1]
对 0 到范围内的数字进行采样。P.shape[0]
例如下面的代码:
P = np.array([[0.2, 0.3],
[0.5, 0.7],
[0.3, 0]])
x = np.random.choice(np.arange(P.shape[0], P[:,0]))
y = np.random.choice(np.arange(P.shape[0], P[:,1]))
将产生我的意志(x=0
在0.2
、x=1
在0.5
和x=2
在0.3
和y=0
在0.3
、y=1
在0.7
)。
就我而言P
,有很多列,我希望一次采样。
当然,我可以在 for 循环中执行此操作,例如:
random_values = np.empty(P.shape[1])
arange_arr = np.arange(P.shape[0])
for i in range(P.shape[1]):
random_values[i] = np.random.choice(arange_arr, p=P[:,i])
试图找到一些优雅的方式来做到这一点。
解决方案
你可以这样做:
P = np.array([[0.2, 0.3],
[0.5, 0.7],
[0.3, 0]])
P_upper = np.cumsum(P, axis=0)
P_lower = np.concatenate((np.zeros((1, P.shape[1])), P_upper[:-1, :]), axis=0)
这将创建一组您可以数字化的 bin。现在生成 0 到 1 之间的随机数:
r = np.random.rand(10, P.shape[1])
有几种方法可以将数据分配到正确的 bin。快速且相对低效的方法是使用布尔掩码:
mask = (r[None, ...] >= P_lower[:, None, :]) & (r[None, ...] < P_upper[:, None, :])
result = np.argmax(mask, axis=0)
一种更有效但更复杂的方法是为每列添加一个偏移量,并将np.digitize
ornp.searchsorted
应用于结果:
offset = np.arange(P.shape[1])
ind = np.searchsorted((P_upper + offset).ravel('F'), (r + offset).ravel('F')).reshape(r.shape, order='F')
result = ind - offset * P.shape[0]
TL;博士
def multi_sample(p, n):
ps = np.cumsum(p, axis=0)
r = np.random.rand(n, ps.shape[1])
offset = np.arange(P.shape[1])
ind = np.searchsorted((P_upper + offset).ravel('F'), (r + offset).ravel('F')).reshape(r.shape, order='F')
return ind - offset * P.shape[0]
推荐阅读
- python - “或”运算符的错误使用
- android - Kotlin:在主要活动中以 OnClick 为条件在辅助活动中设置变量
- c++ - 将结构移植到 MSVC 2017
- python - 如何使用 BeautifulSoup 填写登录表单
- javascript - 如何在 React.js 中使用 JavaScript 修改 CSS
- python - PYTHON:如何抓取字符串的特定部分?
- bash - 如何防止 bash subshell 等待子进程
- reactjs - 重新加载页面 React 后显示 Facebook 评论插件
- python - 是否可以将流中的内容保存到变量而不是位置?
- swift - 传递为参数后如何保存模型?或作为函数获取?核心数据