【问题标题】:Vectorised np.random.choice with varying probabilities具有不同概率的向量化 np.random.choice
【发布时间】:2021-12-07 11:32:31
【问题描述】:

我使用 sklearn 训练了一个机器学习模型,并希望通过根据 predict_proba 概率对预测进行采样来模拟结果。所以我想做类似的事情

samples = np.random.choice(a = possible_outcomes, size = (n_data, n_samples), p = probabilities)

Where probabilities would be is an (n_data, n_possible_outcomes) array

但是 np.random.choice 只允许 p 参数使用一维数组。我目前已经使用类似于以下实现的 for 循环解决了这个问题

sample_outcomes = np.zeros((len(probs), n_samples))
for i in trange(len(probs)):
    sample_outcomes[i, :] = np.random.choice(outcomes, s = n_samples, p=probs[i])

但这相对较慢。任何加快速度的建议将不胜感激!

【问题讨论】:

  • 你可以从索引列表中取样,然后从列表中取出元素
  • 在您的 for 循环实现示例中,sample_outcomes 显然被初始化为一维数组 np.zeros(len(probs)),但您将 sample_outcomes 索引为二维数组。这似乎很奇怪。
  • @jjramsey 抱歉,这是一个错字,我似乎无法编辑它
  • 您遇到这里描述的问题了吗?:meta.stackoverflow.com/questions/315915/…
  • @jjramsey 已修复,谢谢!

标签: python numpy random scikit-learn


【解决方案1】:

如果我理解正确,您想要一种应用choice 的矢量化方式 多次,每次都使用不同的概率向量。 您可以按如下方式手动实现:

import numpy as np

# for reproducibility
np.random.seed(42)

# number of samples
k = 5

# possible outcomes
outcomes = np.arange(10)

# generate a random probability matrix for 15 runs
probabilities = np.random.random((15, 10))
probs = probabilities / probabilities.sum(1)[:, None]

# generate the choices by picking those probabilities above a random generated number
# the higher the value in probs the higher the probability to pick it
choices = probs - np.random.random((15, 10))

# to pick the top k using argpartition need to multiply by -1
choices = -1 * choices

# pick the top k values
res = outcomes[np.argpartition(choices, k, axis=1)][:, :k]

# flatten to match the expected output
print(res.flatten())

输出

[1 8 2 5 3 6 4 8 7 0 1 5 9 3 7 1 4 9 0 8 5 0 4 3 6 8 5 1 2 6 5 3 2 0 6 5 4
 2 3 7 7 9 4 6 1 3 6 4 2 1 4 9 3 0 1 6 9 2 3 8 5 4 7 6 1 5 3 8 2 1 1 0 9 7
 4]

在上面的示例中,代码每次使用不同的概率向量(probs,形状为 15 x 10)从 10 个 (outcomes) 总体中抽取 5 个 (k) 元素 15 次。

【讨论】:

  • 是的,我想为每个数据点绘制一个具有不同概率向量的样本。这个解决方案似乎适用于我的解决方案,并且在长度为 1200000 的数组上速度提高了大约 200 倍。
  • 有没有办法通过替换来做到这一点?我实际上并不需要该应用程序,但我很好奇
  • @Rhys 我认为一个想法是生成一个如上所述的随机浮点矩阵乘以项目数并将其四舍五入为整数,这将生成应用于总体的索引跨度>
【解决方案2】:

我确保我正确理解了您的问题。您可以将samples 创建为大小为n_data * n_samples 的数组,然后使用resize 方法将其调整为正确的大小吗?

samples = np.random.choice(a = possible_outcomes, size = n_data * n_samples, p = probabilities)
samples.resize((n_data, n_samples))

【讨论】:

    【解决方案3】:

    如果我正确理解您的问题,以下是您可以做什么的示例:

    import numpy as np
    #create a list of indices
    index_list = np.arange(len(possible_outcomes))
    # sample indices based on the probabilities
    choice = np.random.choice(a = index_list, size = n_samples, p = probabilities)
    # get samples based on randomly chosen indices
    samples = possible_outcomes[choice]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-02-20
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2012-10-06
      • 1970-01-01
      相关资源
      最近更新 更多