首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在实现对数正态函数时使用Scipy.stats是不是做错了什么?

在实现对数正态函数时使用Scipy.stats是不是做错了什么?
EN

Stack Overflow用户
提问于 2018-06-05 01:29:11
回答 1查看 68关注 0票数 0

我可能已经脑死亡了,但我的代码定义了一个使用Scipy.stats在Python中进行操作的对数正态类。

我的类看起来像这样:

LogNorm类:

代码语言:javascript
复制
def __init__(self, mean, sd, offset=0) :
# uses 'real' units -i.e., 100000, 15000 for mean and sdn
    self.mean = mean
    self.sd = sd
    self.offset = offset
    self.xvar_mu, self.xvar_sigma = get_base_mu_and_sigma(mean, sd)
    self.mean = np.exp(self.xvar_mu + self.xvar_sigma**2.0/2.0)   # reflect that change in the Y 
    self.sd = ((np.exp(self.xvar_sigma**2.0) - 1.0) *
               (np.exp(2.0 * self.xvar_mu + self.xvar_sigma**2.0))) ** 0.5
    self.RV = lognorm(s = self.xvar_sigma, scale = self.mean, loc = self.offset)  # fozen

这里的想法是传入对数正态本身的平均值和sd。我为后人记录了这些(假设偏移量= 0.0,按照默认值)。然后我有一个辅助函数,它将这些映射到作为对数正态分布基础的正态分布的µ和sigma。该函数如下所示,如果有用的话:

代码语言:javascript
复制
def get_base_mu_and_sigma(mean, sd) :
    mu = math.log(mean**2.0 / (sd**2.0 + mean**2.0)**0.5)
    sigma = (math.log(1.0 + sd**2.0/mean**2.0))**0.5
    return (mu, sigma)

这直接来自维基百科,看起来是对的(查看“算术时刻”部分的结尾):https://en.wikipedia.org/wiki/Log-normal_distribution

然后,'self.RV‘变成一个’冻结的‘RV,并有一堆内置/继承的函数(mean(),median(),var()等),这些函数与µ和sigma描述的对数正态相关。

我遇到的挑战是,当我创建这样一个对象,然后尝试检查均值和sd (通过方差的平方根),数字似乎不匹配。例如,使用mean = 110517.09和sd = 2210.34 (来自我的应用程序),当我随后执行以下代码时,我得到了不一致的结果:

代码语言:javascript
复制
        p = rv1.RV.pdf(x)
        print("rv1.mean, rv1.sd = " + str(rv1.mean) + "  " + str(rv1.sd))
        print("rv1.mean(), rv1.var()**0.5 = " + str(rv1.RV.mean()) + "  " + str(rv1.RV.var()**0.5))

提供:

代码语言:javascript
复制
rv1.mean, rv1.sd = 110517.09180756475  2210.341836151173
rv1.mean(), rv1.var()**0.5 = 110539.19301602637  2210.783860320406

你知道我做错了什么吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-05 06:21:51

您使用self.mean作为scipy.stats.lognormscale参数,但这是不正确的。引用自docstring for lognorm

对数正态随机变量Y的常见参数化是根据唯一的正态分布随机变量exp(X) = Y的平均值、mu和标准差sigma,使得X (X)=Y。该参数化对应于设置s = sigmascale = exp(mu)

因此,当您通过调用lognorm创建self.RV时,scale参数必须为np.exp(self.xvar_mu)。(假设offset为0。)

下面是一个使用您的函数get_base_mu_and_sigma来转换参数的简化示例。

首先,下面是您使用的函数和示例值:

代码语言:javascript
复制
In [154]: def get_base_mu_and_sigma(mean, sd) :
     ...:     mu = math.log(mean**2.0 / (sd**2.0 + mean**2.0)**0.5)
     ...:     sigma = (math.log(1.0 + sd**2.0/mean**2.0))**0.5
     ...:     return (mu, sigma)
     ...: 

In [155]: mean = 110517.09180756475

In [156]: sd = 2210.341836151173

获取基础正态分布的参数:

代码语言:javascript
复制
In [157]: mu, sigma = get_base_mu_and_sigma(mean, sd)

创建一个scipy的lognorm分布的实例,并验证该分布的均值和标准差是否与meansd匹配

代码语言:javascript
复制
In [158]: ln = lognorm(s=sigma, loc=0, scale=np.exp(mu))

In [159]: ln.mean()
Out[159]: 110517.09180756476

In [160]: ln.std()
Out[160]: 2210.341836151174
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50685839

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档