我想实现一个简单的方法来从 C# 中的多项分布中采样(第一个参数是我们要采样的整数数组,第二个参数是选择每个整数的概率)。
当我在 python 中使用 numpy 执行此操作时,结果是有意义的。
np.random.choice(np.array([1,2,3,4,5,6]),p=np.array([.624,.23,.08,.04, .02, .006]),size=len(b))
我得到很多 1(概率 62%)、一堆 2、一些 3 等。
但是,当我在 C# 中尝试下面的实现时(非常简单的多项式逆变换采样,仅依赖于统一的随机变量),我得到了非常奇怪的结果。对于所有 1000 个样本,我经常会找到全 1。有时,我会找到所有 3 的 (!!??)。结果永远不会像您期望的那样(以及您从 python 函数中获得的结果 - 尝试自己运行几次)。这真的很可怕,因为我们依赖这些原语。有没有人了解 C# 版本可能有什么问题?
static void Main(string[] args)
{
int[] iis = new int[7];
int[] itms = new int[] { 1, 2, 3, 4, 5, 6 };
double[] probs = new double[] { .624, .23, .08, .04, .02, .006 };
for (int i = 0; i < 1000; i++)
{
iis[MultinomialSample(itms, probs)] += 1;
}
foreach (var ii in iis)
{
Console.Write(ii + ",");
}
Console.Read();
}
private static int MultinomialSample(int[] s, double[] ps)
{
double[] cumProbs = new double[ps.Length];
cumProbs[0] = ps[0];
for (int i = 1; i < ps.Length; i++)
{
cumProbs[i] = cumProbs[i - 1] + ps[i];
}
Random random = new Random();
double u = random.NextDouble();
for (int i = 0; i < cumProbs.Length - 1; i++)
{
if (u < cumProbs[i])
{
return s[i];
}
}
return s[s.Length - 1];
}