在机器学习任务中。我们应该得到一组带有边界的随机w.r.t正态分布。我们可以使用np.random.normal()
获得正态分布数,但它不提供任何绑定参数。我想知道怎么做?
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)
>>> X = get_truncated_normal(mean=8, sd=2, low=1, upp=10)
>>> X.rvs()
6.0491227353928894
>>> X.rvs(10)
array([ 7.70231607, 6.7005871 , 7.15203887, 6.06768994, 7.25153472,
5.41384242, 7.75200702, 5.5725888 , 7.38512757, 7.47567455])
以下是三种不同截断正态分布的图:
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()
如果您正在寻找Truncated normal distribution,SciPy有一个名为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的直方图:
除了@bakkal建议(+1)你可能还想看看Vincent Mazet配方实现这个,由py-rtnorm重写为Christoph Lassner模块。
如果你只想和numpy
一起工作,你也可以这样做:
int(np.clip(int(np.random.normal(mean,std)),min_size,max_size)
这只会将较小和较大的值剪切到指定的min
和max