我试图获取对数正态分布的均值和标准差,其中mu = 0.4104857306和sigma = 3.4070874277012617,我期望均值= 500和std = 600。我不确定我做错了什么。这是代码:
import scipy.stats as stats
import numpy as np
a = 3.4070874277012617
b = 0.4104857306
c = stats.lognorm.mean(a,b)
d = stats.lognorm.var(a,b)
e = np.sqrt(d)
print("Mean =",c)
print("std =",e)
输出在这里:
Mean = 332.07447304207903
sd = 110000.50047821256
谢谢。
编辑:
感谢您的帮助。我检查了一下,发现有一些计算错误。我现在可以得到mean = 500,但仍然不能得到std = 600。这是我使用的代码:
import numpy as np
import math
from scipy import exp
from scipy.optimize import fsolve
def f(z):
mean = 500
std = 600
sigma = z[0]
mu = z[1]
f = np.zeros(2)
f[0] = exp(mu + (sigma**2) / 2) - mean
f[1] = exp(2*mu + sigma**2) * exp(sigma**2 - 1) - std**2
return f
z = fsolve (f,[1.1681794012855686,5.5322865416282365])
print("sigma =",z[0])
print("mu =",z[1])
print(f(z))
sigma = 1.1681794012855686
mu = 5.5322865416282365
我尝试使用计算器检查结果,并且可以根据需要获取std = 600,但仍可以使用853.5698320847896
来获取lognorm.std(sigma, scale=np.exp(mu))
。
答案 0 :(得分:3)
scipy.stats.lognorm
的对数正态分布以一种稍微不寻常的方式进行参数设置,以便与其他连续分布保持一致。第一个参数是shape参数,即您的sigma
。随后是loc
和scale
参数,它们允许移动和缩放分布。在这里,您需要loc=0.0
和scale=exp(mu)
。因此,要计算均值,您需要执行以下操作:
>>> import numpy as np
>>> from scipy.stats import lognorm
>>> mu = 0.4104857306
>>> sigma = 3.4070874277012617
>>> lognorm.mean(sigma, 0.0, np.exp(mu))
500.0000010889041
或更明确地说:按名称传递scale
参数,并将loc
参数保留为默认值0.0
:
>>> lognorm.mean(sigma, scale=np.exp(mu))
500.0000010889041
正如@coldspeed在他的评论中所说,您对标准偏差的期望值看起来不正确。我得到:
>>> lognorm.std(sigma, scale=np.exp(mu))
165831.2402402415
我用手计算得出相同的值。
要再次检查这些参数选择是否确实能够提供预期的对数正态,我创建了一个百万个偏差的样本,并查看了该样本的对数的均值和标准偏差。不出所料,这些值使我返回的值大致类似于原始的mu
和sigma
:
>>> samples = lognorm.rvs(sigma, scale=np.exp(mu), size=10**6)
>>> np.log(samples).mean() # should be close to mu
0.4134644116056518
>>> np.log(samples).std(ddof=1) # should be close to sigma
3.4050012251732285
作为对编辑的回应:您已经获得了对数正态的方差略有错误的公式-您需要将exp(sigma**2 - 1)
项替换为(exp(sigma**2) - 1)
。如果执行此操作,然后重新运行fsolve
计算,则会得到:
sigma = 0.9444564779275075
mu = 5.768609079062494
使用这些值,您应该获得预期的平均值和标准偏差:
>>> from scipy.stats import lognorm
>>> import numpy as np
>>> sigma = 0.9444564779275075
>>> mu = 5.768609079062494
>>> lognorm.mean(sigma, scale=np.exp(mu))
499.9999999949592
>>> lognorm.std(sigma, scale=np.exp(mu))
599.9999996859631
给定所需的均值和标准差,也可以使用解析方法求解fsolve
和sigma
,而不必使用mu
。这样可以更快地提供更准确的结果:
>>> mean = 500.0
>>> var = 600.0**2
>>> sigma = np.sqrt(np.log1p(var/mean**2))
>>> mu = np.log(mean) - 0.5*sigma*sigma
>>> mu, sigma
(5.768609078769636, 0.9444564782482624)
>>> lognorm.mean(sigma, scale=np.exp(mu))
499.99999999999966
>>> lognorm.std(sigma, scale=np.exp(mu))
599.9999999999995