这称为截断正态分布:
http://en.wikipedia.org/wiki/Truncated_normal_distribution
克里斯蒂安·罗伯特(Christian Robert)在这里写了一种针对各种情况的方法(根据截断点的位置使用不同的方法):
Robert, CP (1995)“截断正态变量的模拟”,
统计与计算,第 5 卷,第 2 期,6 月,第 121-125 页
论文可在 http://arxiv.org/abs/0907.4010
这讨论了针对不同截断点的许多不同想法。这不是以任何方式接近这些的唯一方法,但它通常具有相当不错的性能。如果你想用不同的截断点做很多不同的截断法线,这将是一个合理的方法。正如您所指出的,msm::tnorm
它基于 Robert 的方法,同时truncnorm::truncnorm
实现了 Geweke (1991) 的接受-拒绝采样器;这与罗伯特论文中的方法有关。请注意,它以通常的方式msm::tnorm
包括密度、cdf 和分位数(逆 cdf)函数。R
较早的方法参考是Luc Devroye 的书;自从它绝版以来,他收回了版权并提供了下载。
您的特定示例与对截断为 1 的标准法线进行采样相同(如果吨是截断点,( t - μ ) / σ= ( 5 - 3 ) / 2 = 1),然后缩放结果(乘以σ并添加μ)。
在这种特定情况下,罗伯特建议您的想法(在第二个或第三个化身中)是非常合理的。大约 84% 的时间你会得到一个可接受的值,因此生成大约1.19 n平均法线(您可以计算出界限,以便使用矢量化算法生成足够的值,比如 99.5% 的时间,然后偶尔生成最后几个效率较低的值 - 甚至一次生成一个)。
这里还讨论了 R 代码中的实现(以及 Rccp 中对同一问题的另一个答案,但那里的 R 代码实际上更快)。那里的纯 R 代码在 6 毫秒内生成 50000 个截断的法线,尽管那个特定的截断法线只切断了极端的尾部,所以更实质性的截断意味着结果更慢。它通过计算应该生成多少以几乎可以肯定获得足够的数量来实现生成“太多”的想法。
如果我多次只需要一种特定类型的截断法线,我可能会考虑采用 ziggurat 方法或类似方法的一个版本来解决问题。
事实上,尼古拉斯肖邦似乎已经这样做了,所以我不是唯一一个想到:
http://arxiv.org/abs/1201.6140
他讨论了其他几种算法,并将他的算法的 3 个版本与其他算法的时间进行比较,以生成 10^8 个随机法线用于各种截断点。
不出所料,他的算法速度相对较快。
从论文中的图表来看,即使是他比较的最慢的算法,在(对他们而言)最差的截断点也会产生108大约 3 秒内的值 - 这表明如果实施得当,那里讨论的任何算法都可能是可接受的。
编辑:这里提到了我不确定的一个(但也许它在其中一个链接中)是转换(通过逆法线 cdf)截断的制服 - 但可以通过简单地在截断范围内生成制服来截断制服. 如果逆正态 cdf 很快,这既快速又简单,并且适用于各种截断点。