numpy 如何从分类分布中抽取样本

olqngx59  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(102)

我有一个3D numpy数组,其中包含最后一个维度中每个类别的概率。例如:

import numpy as np
from scipy.special import softmax

array = np.random.normal(size=(10, 100, 5))
probabilities = softmax(array, axis=2)

字符串
我如何从具有这些概率的分类分布中抽样?
编辑:现在我是这样做的:

def categorical(x):
    return np.random.multinomial(1, pvals=x)

samples = np.apply_along_axis(categorical, axis=2, arr=probabilities)


但它非常慢,所以我想知道是否有一种方法来矢量化这个操作。

p8ekf7hl

p8ekf7hl1#

从给定的概率分布中抽取样本是通过构建评估0到1范围内的随机数的逆累积分布来完成的。对于少数离散类别-如问题中-您可以使用线性搜索找到逆:

## Alternative test dataset
probabilities[:, :, :] = np.array([0.1, 0.5, 0.15, 0.15, 0.1])

n1, n2, m = probabilities.shape

cum_prob = np.cumsum(probabilities, axis=-1) # shape (n1, n2, m)
r = np.random.uniform(size=(n1, n2, 1))

# argmax finds the index of the first True value in the last axis.
samples = np.argmax(cum_prob > r, axis=-1)

print('Statistics:')
print(np.histogram(samples, bins=np.arange(m+1)-0.5)[0]/(n1*n2))

字符串
对于测试数据集,典型的测试输出为:

Statistics:
[0.0998 0.4967 0.1513 0.1498 0.1024]


看起来没问题
如果你有很多很多的类别(上千个),最好使用numba编译函数进行二分搜索。

lokaqttq

lokaqttq2#

您可以使用np.random.choice函数。它有一个方便的p参数,允许您指定每个类别的概率。参见下面的工作示例

import numpy as np
categories = ['apple', 'banana', 'kiwi']
probabilities = [0.2, 0.2, 0.6]

# draw 1000 samples
n = 1000
draw = np.random.choice(categories, n, p=probabilities)

# print counts to verify
from collections import Counter
print(Counter(draw))

字符串

相关问题