Cat*_*gia 28 python random numpy gaussian scipy
IOK所以我希望能够从正常分布中选择只能介于0和1之间的值.在某些情况下,我希望能够基本上只返回一个完全随机的分布,而在其他情况下我想返回值落在高斯的形状.
目前我正在使用以下功能:
def blockedgauss(mu,sigma):
while True:
numb = random.gauss(mu,sigma)
if (numb > 0 and numb < 1):
break
return numb
Run Code Online (Sandbox Code Playgroud)
它从正态分布中选取一个值,如果它超出0到1的范围,则丢弃它,但我觉得必须有更好的方法来做到这一点.
unu*_*tbu 32
听起来你想要一个截断的正态分布.使用scipy,您可以使用scipy.stats.truncnorm
从这样的分布生成随机变量:
import matplotlib.pyplot as plt
import scipy.stats as stats
lower, upper = 3.5, 6
mu, sigma = 5, 0.7
X = stats.truncnorm(
(lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
N = stats.norm(loc=mu, scale=sigma)
fig, ax = plt.subplots(2, sharex=True)
ax[0].hist(X.rvs(10000), normed=True)
ax[1].hist(N.rvs(10000), normed=True)
plt.show()
Run Code Online (Sandbox Code Playgroud)
上图显示了截断的正态分布,下图显示了具有相同均值mu
和标准差的正态分布sigma
.
小智 11
我在寻找一种方法来查找从零和1之间截断的正态分布(即概率)中采样的一系列值时遇到了这篇文章.为了帮助遇到同样问题的其他人,我只想注意scipy.stats.truncnorm具有内置功能".rvs".
因此,如果您想要100,000个样本,平均值为0.5,标准差为0.1:
import scipy.stats
lower = 0
upper = 1
mu = 0.5
sigma = 0.1
N = 100000
samples = scipy.stats.truncnorm.rvs(
(lower-mu)/sigma,(upper-mu)/sigma,loc=mu,scale=sigma,size=N)
Run Code Online (Sandbox Code Playgroud)
这给出了一个非常类似于numpy.random.normal的行为,但是在所需的范围内.使用内置将比循环收集样本快得多,特别是对于大的N值.
我通过以下方式制作了一个示例脚本。它展示了如何使用 API 来实现我们想要的功能,例如生成具有已知参数的样本,如何计算 CDF、PDF 等。我还附上了一张图片来展示这一点。
#load libraries
import scipy.stats as stats
#lower, upper, mu, and sigma are four parameters
lower, upper = 0.5, 1
mu, sigma = 0.6, 0.1
#instantiate an object X using the above four parameters,
X = stats.truncnorm((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
#generate 1000 sample data
samples = X.rvs(1000)
#compute the PDF of the sample data
pdf_probs = stats.truncnorm.pdf(samples, (lower-mu)/sigma, (upper-mu)/sigma, mu, sigma)
#compute the CDF of the sample data
cdf_probs = stas.truncnorm.cdf(samples, (lower-mu)/sigma, (upper-mu)/sigma, mu, sigma)
#make a histogram for the samples
plt.hist(samples, bins= 50,normed=True,alpha=0.3,label='histogram');
#plot the PDF curves
plt.plot(samples[samples.argsort()],pdf_probs[samples.argsort()],linewidth=2.3,label='PDF curve')
#plot CDF curve
plt.plot(samples[samples.argsort()],cdf_probs[samples.argsort()],linewidth=2.3,label='CDF curve')
#legend
plt.legend(loc='best')
Run Code Online (Sandbox Code Playgroud)
如果有人只想使用numpy解决方案,这是一个使用常规函数和剪辑的简单实现(MacGyver的方法):
import numpy as np
def truncated_normal(mean, stddev, minval, maxval):
return np.clip(np.random.normal(mean, stddev), minval, maxval)
Run Code Online (Sandbox Code Playgroud)
编辑:不要使用这个!这就是你不应该这样做的方法!例如,
a = truncated_normal(np.zeros(10000), 1, -10, 10)
可能看起来像它的工作原理,但
b = truncated_normal(np.zeros(10000), 100, -1, 1)
将肯定不会得出一个截断正常的,因为你可以在下面的柱状图看:
抱歉,希望没人受伤!我想这课是,不要尝试在编码时模仿MacGyver ...干杯,
安德烈斯
归档时间: |
|
查看次数: |
23141 次 |
最近记录: |