微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何最好地从截断的正态分布中获取样本?

如何解决如何最好地从截断的正态分布中获取样本?

我已经进行了一些搜索,但似乎无法找到一种合理的方法来从截断的正态分布中进行采样。

我没有被截断:

samples = [np.random.normal(loc=x,scale=d) for (x,d) in zip(X,D)]

XD是浮点列表。

目前,我正在像这样实现截断:

def truncnorm(loc,scale,bounds):
  s = np.random.normal(loc,scale)
  if s > bounds[1]:
    return bounds[1]
  elif s < bounds[0]:
    return bounds[0]
  return s

samples = [truncnorm(loc=x,scale=d,bounds=b) for (x,d,b) in zip(X,D,bounds)]

bounds元组列表(min,max)

这种方法有点尴尬,所以我想知道是否有更好的方法

解决方法

返回它们之外的样本的边界值,将导致过多的样本落在边界上。这并不代表实际的分布。边界上的值需要被拒绝,并用新的样本替换。这样的代码可能是:

def test_truncnorm(loc,scale,bounds):
    while True:
        s = np.random.normal(loc,scale)
        if bounds[0] <= s <= bounds[1]:
            break
    return s

在狭窄范围内,这可能会非常慢。 Scipy的truncnorm更有效地处理了这种情况。出乎意料的是,边界以标准法线的功能表示,因此您的调用将是:

s = scipy.stats.truncnorm.rvs((bounds[0]-loc)/scale,(bounds[1]-loc)/scale,loc=loc,scale=scale)

请注意,使用numpy的vectorization and broadcasting时scipy的工作速度更快。一旦您习惯了这种记号,它的书写和阅读也将变得更加简单。所有样本可以一口气计算出来:

X = np.array(X)
D = np.array(D)
bounds = np.array(bounds)
samples = scipy.stats.truncnorm.rvs((bounds[:,0] - X) / D,(bounds[:,1] - X) / D,loc=X,scale=D)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。