高效有界偏置随机数发生器

时间:2013-07-30 00:49:30

标签: java algorithm math statistics

上下文

基于人口的增量学习(PBIL)算法的一部分是计算许多偏置随机比特。每个位的偏置由0.0-1.0范围内的相应双精度确定。

对于每个位,将0.0-1.0范围内的无偏差随机双精度与偏差进行比较。如果生成的随机双精度小于偏差,则将该位设置为0,否则为1。

在生成比特偏置序列后,比特将转换为各种范围内的双精度数。

问题

我想直接在一个范围内生成一个有偏差的双。这是在没有操纵双重表示中的每个位的情况下。然后,每个双精度数将具有确定偏差的单个变量(每个位不是一个)。如前所述,每个double也有一个最小和最大常数,它决定了随机双数的下限和上限。

以下示例生成可接受的分布。然而,如果没有潜在的无限循环,解决问题会很好。

public double getBiasedRandom(double bias, double min, double max) {
    double rndBiased;
    double variance = (max-min)*0.3;

    do {
         rndBiased = bias + (random.nextGaussian() * variance);
    } while(rndBiased < min && rndBiased <= max);

    return rndBiased;
}

解决方案不必返回相同的分布,但是边界内的所有值必须是任何偏差的可能结果。更接近偏差的值应该比远离的值更可能。我不知道多少钱。理想情况下,它将由可以通过实验设置的变量确定。在上面的例子中,这个变量是常数0.3。

我试图研究不同的发行版,但我的数学技能不足。还要记住,性能至关重要,而且近似但有效的解决方案可能是有利的。出于同样的原因,依赖加权表的解决方案可能不值得。

编辑:在Cristiano Zambon的回答中添加了一个潜在的解决方案。

1 个答案:

答案 0 :(得分:1)

如果我理解得很好,你只需要一个函数,在偏差时返回一个随机编号的“居中”,并且总是在{min; max}范围内......

怎么样:

public double getBiasedRandom(double bias, double min, double max) {
    double bias_depth_perc = 0.1;
    double bias_depth_abs = (max - min)*bias_depth_perc;
    double min_bias = bias - bias_depth;
    double max_bias = bias + bias_depth;
    Random tRandom = new Random();

    if (max_bias > max) max_bias = max;
    if (min_bias < min) min_bias = min;

    double variance = (max_bias - min_bias)/2;


    double rndBiased = bias + tRandom .nextGaussian() * aVariance;

    if (rndBiased > max)
       rndBiased = max - (rndBiased - max);

    if (rndBiased < min)
       rndBiased = min + (min - rndBiased);

    return rndBiased;
}

实际上,您只需使用以偏差为中心的高斯分布得到偏差随机数,其方差可以设置为范围的百分比(在示例中设置为10%,行double bias_depth_perc = 0.1)。

编辑:当偏差接近边界时改变了行为,并且您获得了超出限制的大量随机数。现在它只是将边界内随机生成的数字复制到距离限制本身的距离。这实际上以简单的不对称分布结束。

第二个解决方案: 这有点棘手。这里的想法是始终生成对称的随机数,然后将生成的数字映射到正确的范围。例如:如果你有:

  • min = 0
  • max = 1
  • bias = 0.1

首先生成一个以0.5为中心的随机数,并选择方差:

  • rnd = 0.5 tRandom.nextGaussian()* variance;

然后,如果rnd是&gt; 0.5,你将它映射到范围{bias;偏差+ max_bias}与简单的尺度moltiplication。 如果rnd是&lt; 0.5,你把它映射到范围{min_bias;偏压}。

这是代码:

public double getBiasedRandom(double bias, double min, double max) {
    double centered_depth_perc = 0.3;
    double centered_depth_abs = (max - min)*centered_depth_perc;
    double center = 0.5;

    Random tRandom = new Random();  
    double rndCentered = center  + tRandom .nextGaussian() * centered_depth_abs; // generate centered random number. 

    if (rndCentered >= center)
        rndBiased = (rndCentered - center) * (max - bias) + bias;
    else
        rndBiased = bias - (center - rndCentered) * (bias - min);

    // the following two tests will be as more important as centered_depth_perc 
    // get bigger. 
    if (rndBiased > max) 
       rndBiased = max;

    if (rndBiased < min)
       rndBiased = min;

    return rndBiased;
}
希望它可以提供帮助。