【问题标题】:How to generate random number in range of truncated normal distribution如何在截断正态分布范围内生成随机数
【发布时间】:2021-09-01 06:38:56
【问题描述】:

我需要生成一个截断正态分布范围内的值,例如在python中你可以使用scipy.stats.truncnorm()来制作

def get_truncated_normal(mean=.0, sd=1., low=.0, upp=10.):
    return truncnorm((low - mean) / sd, (upp - mean) / sd, loc=mean, scale=sd)

如何描述here

是否有任何包可以在 go 中做点什么或者我应该自己编写以下函数?

我尝试遵循doc 的说法,但它使数字不在所需范围内:

func GenerateTruncatedNormal(mean, sd uint64) float64 {
    return rand.NormFloat64() * (float64)(sd + mean)
}
GenerateTruncatedNormal(10, 5)

得到 16.61、-14.54 甚至 32.8,但由于mean = 10,我预计得到 15 的可能性很小 -> 10 + 5 = 15 是我们可以获得的最大值。这里有什么问题? ????

【问题讨论】:

  • 您没有正确使用 NormFloat64()(应该是 rand.NormFloat64() * float64(sd) + float64(mean)),但这不是截断的正态分布——它是正态分布。我不相信有任何软件包可以提供该发行版,因此您必须自己实现它。
  • 虽然不是很清楚这就是你想要的——你的GenerateTruncatedNormal 函数没有lowupp 参数,比如来自python 的get_truncated_normal,所以看起来有些不对劲。
  • @PaulHankin,正如文档所说的NormFloat64 returns a normally distributed float64 in the range [-math.MaxFloat64, +math.MaxFloat64] with standard normal distribution (mean = 0, stddev = 1) from the default Source. To produce a different normal distribution, callers can adjust the output using,所以我想可以使用我在函数中传递的这两个参数来调整函数的结果
  • 抱歉,您正在回复我,但我不确定您想要什么回复。也许您是说您认为文档说您可以编写 rand.NormFloat64() * a + b 来获得截断的正态分布,但如果是这样,那就错了——您会得到一个 sd a 和均值 b 的正态分布。
  • @PaulHankin,你是对的,我对文档的处理是错误的。感谢您的回复:D

标签: go random normal-distribution


【解决方案1】:

实现这一目标的一种方法是

  • 从正态分布生成一个数字x,并带有所需的均值和标准差参数,
  • 如果超出范围 [low..high],则将其丢弃并重试。

这尊重了正态分布的Probability Density Function,有效地切掉了左右尾巴。

func TruncatedNormal(mean, stdDev, low, high float64) float64 {
    if low >= high {
        panic("high must be greater than low")
    }

    for {
        x := rand.NormFloat64()*stdDev + mean
        if low <= x && x < high {
            return x
        }
        // fmt.Println("missed!", x)
    }
}

Playground

如果 [low..high] 区间非常窄,则需要更多计算时间,因为更多生成的数字将被丢弃。但是,它在实践中仍然收敛得非常快。

我检查了上面的代码,将其结果与scipy's truncnorm 的结果进行了比较,并得出了相同的图表。

【讨论】:

  • 现在我意识到“如果 [low..high] 区间非常窄”,那么所需的 PDF 看起来像一条直线,这可能不是基于正态分布的典型用法.