从列表中选择随机项目给出每个项目的概率

时间:2016-06-28 21:20:44

标签: c# random probability n-gram

对于严厉措辞的标题抱歉...

我有一个名为NGram的对象

class NGram
{
     //other properties
     double Probability {get; set;} //Value between 1 and 0 
}

现在假设我有这些对象的列表,这样......

List<NGrams> grams = GetNGrams();
Debug.Assert(grams.Sum(x => x.Probability) == 1);

如何在考虑概率分布的同时从此列表中选择随机项。

例如,假设grams[0].Probability == 0.5那么应该有50%的机会选择grams[0]

我想我可能需要像rand.NextDouble()这样的东西,但我很遗憾。

4 个答案:

答案 0 :(得分:2)

按列表排序,按概率排序,升序。

汇总列表中所有元素的概率字段。我们称之为 P

在[0, P ]之间获取一个随机数,让我们称之为 r

迭代列表,同时保持概率总和的累加值,直到您正在迭代的当前元素( pe )。找到 pe &gt; = r

的第一个元素时结束搜索

数组中所有元素的总和为1的情况现在只是一个特例:)

答案 1 :(得分:2)

这是一种更通用的方法(意味着你不需要断言概率加1):

static Random rand = new Random();

public NGram GetRandom(IEnumerable<NGram> pool)
{
     // get universal probability 
     double u = pool.Sum (p => p.Probability);

     // pick a random number between 0 and u
     double r = rand.NextDouble() * u;

     double sum = 0;
     foreach(NGram n in pool)
     {
         // loop until the random number is less than our cumulative probability
         if(r <= (sum = sum + n.Probability))
         {
            return n;
         }
     }
     // should never get here
     return null;
}

答案 2 :(得分:1)

试试这个:

List<NGram> grams = new List<NGram>()
{
    new NGram() { Probability = 0.5 },
    new NGram() { Probability = 0.35 },
    new NGram() { Probability = 0.15 }
};

var rnd = new Random();

var result =
    grams
        .Aggregate(
            new { sum = 0.0, target = rnd.NextDouble(), gram = (NGram)null },
            (a, g) =>
                a.gram == null && a.sum + g.Probability >= a.target
                    ? new { sum = a.sum + g.Probability, a.target, gram = g }
                    : new { sum = a.sum + g.Probability, a.target, a.gram });

它给我这样的结果:

gcloud-python

答案 3 :(得分:0)

在伪代码中

r = Get a random number between 0 and 1
sum = 0
i = 0
Loop  
    sum = sum + grams[i].Probability  
    If sum >= r Then  
        Exit Loop
    End
    i = i + 1  
End
i is the index of the random item in the list

这个想法是总结项目的概率,直到总和大于或等于随机数。由于概率总和为1且随机数在0 .. 1范围内,因此无论如何都会找到一个项目。更有可能选择概率更高的项目。

∑P= 0 0.08     0.3 0.43 0.53          0.88  1
    +--+--------+----+---+-------------+----+
    |  |        |    |   |             |    |
    +--+--------+----+---+-------------+----+ 
i =  0      1      2   3       4         5  

您可以想象每个项目的长度等于其指定的概率。该算法就像是在长度为1的标尺上随机投掷飞镖,所有概率沿着标尺堆叠起来。项目被击中的概率与其大小(即其分配的概率)成比例。