如何在numpy范围内获得正态分布?

时间:2016-04-27 15:24:24

标签: python numpy random machine-learning normal-distribution

在机器学习任务中。我们应该得到一组带有边界的随机w.r.t正态分布。我们可以使用np.random.normal()获得正态分布号,但它不提供任何绑定参数。我想知道怎么做?

5 个答案:

答案 0 :(得分:34)

truncnorm参数化很复杂,所以这里有一个将参数化转换为更直观的函数:

from scipy.stats import 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)

如何使用?

  1. 使用参数实例生成器:表示标准差截断范围

    >>> X = get_truncated_normal(mean=8, sd=2, low=1, upp=10)
    
  2. 然后,您可以使用X生成值:

    >>> X.rvs()
    6.0491227353928894
    
  3. 或者,具有N个生成值的numpy数组:

    >>> X.rvs(10)
    array([ 7.70231607,  6.7005871 ,  7.15203887,  6.06768994,  7.25153472,
            5.41384242,  7.75200702,  5.5725888 ,  7.38512757,  7.47567455])
    
  4. 可视化示例

    以下是三种不同的截断正态分布图:

    X1 = get_truncated_normal(mean=2, sd=1, low=1, upp=10)
    X2 = get_truncated_normal(mean=5.5, sd=1, low=1, upp=10)
    X3 = get_truncated_normal(mean=8, sd=1, low=1, upp=10)
    
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots(3, sharex=True)
    ax[0].hist(X1.rvs(10000), normed=True)
    ax[1].hist(X2.rvs(10000), normed=True)
    ax[2].hist(X3.rvs(10000), normed=True)
    plt.show()
    

    enter image description here

答案 1 :(得分:12)

如果您正在寻找Truncated normal distribution,Sci​​Py有一个名为truncnorm的功能

  

此分布的标准形式是标准正常截断   到范围[a,b] - 注意a和b是在域上定义的   标准正常。转换特定均值的剪辑值和   标准差,使用:

     

a,b =(myclip_a - my_mean)/ my_std,(myclip_b - my_mean)/ my_std

     

truncnorm将a和b作为形状参数。

>>> from scipy.stats import truncnorm
>>> truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10)
array([-1.83136675,  0.77599978, -0.01276925,  1.87043384,  1.25024188,
        0.59336279, -0.39343176,  1.9449987 , -1.97674358, -0.31944247])

以上示例以-2和2为界,并返回10个随机变量(使用.rvs()方法)

>>> min(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
-1.9996074381484044
>>> max(truncnorm(a=-2/3., b=2/3., scale=3).rvs(size=10000))
1.9998486576228549

这里是-6,6的直方图:

enter image description here

答案 2 :(得分:1)

除了@bakkal建议(+1)之外,您可能还需要查看Vincent Mazet配方以实现此目的,并按py-rtnorm重写为Christoph Lassner模块。

答案 3 :(得分:0)

如果您只想使用numpy,也可以执行以下操作:

int(np.clip(int(np.random.normal(mean,std)),min_size,max_size)

这只会将较小和较大的值剪切到您指定的minmax

答案 4 :(得分:0)

您可以将目标范围(按惯例)细分为相等的分区,然后计算每个区域的积分,然后根据表面在每个分区上调用统一方法。 它是在python中实现的:

quad_vec(eval('scipy.stats.norm.pdf'), 1, 4,points=[0.5,2.5,3,4],full_output=True)