Inf值scipy.stats.truncnorm

时间:2018-12-27 16:22:03

标签: python scipy

我正在使用此代码从截断的法线中采样:

np.random.seed(1234)
Z = truncnorm.rvs(a = 31.399904/0.822358, b = np.inf, loc = 31.399904, scale = 0.822358)

它为Z生成inf值,这与我的其余代码混在一起。您是否有办法避免这种情况?

1 个答案:

答案 0 :(得分:0)

如果要在[lower, upper]上支持truncnorm,请使用

X = stats.truncnorm(
    (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)

例如,如果您想要[31.399904, np.inf]上支持的截断范数 平均值为32,标准偏差为0.822358,那么您将使用

import scipy.stats as stats
import matplotlib.pyplot as plt

lower, upper = 31.399904, np.inf
mu, sigma = 32, 0.822358
X = stats.truncnorm(
    (lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)
N = stats.norm(loc=mu, scale=sigma)
data = X.rvs(10000)

fig, ax = plt.subplots(2, sharex=True)
ax[0].hist(data, density=True)
ax[1].hist(N.rvs(10000), density=True)
plt.show()

enter image description here

上方的直方图显示了截断范本中样本的分布,下方的直方图显示了均值和标准差均相同的标准法线样本的分布。


如果您还希望均值mu等于支撑的左端点,则可以使用

lower, upper = 31.399904, np.inf
mu, sigma = lower, 0.822358
Z = stats.truncnorm.rvs((lower - mu) / sigma, (upper - mu) / sigma, loc=mu, scale=sigma)

等效于

Z = stats.truncnorm.rvs(0, np.inf, loc=31.399904, scale=0.822358)

例如,

In [47]: np.random.seed(1234)
In [49]: stats.truncnorm.rvs(0, np.inf, loc=31.399904, scale=0.822358)
Out[49]: 31.599232630594255

问题

Z = truncnorm.rvs(a = 31.399904/0.822358, b = np.inf, loc = 31.399904, scale = 0.822358)

平均值在loc = 31.3999904,但左端点在38.2左右:

In [51]: a = 31.399904/0.822358; a
Out[51]: 38.18276711602489

truncnorm最可能的值应该是平均值,但是平均值不在支撑[38.2, np.inf]之外。这种矛盾导致了行为的怪异。