拟合自定义 Scipy 分布
Fitting a Custom Scipy Distribution
我已经使用自定义 scipy class 重新定义了对数正态分布。我已经模拟了这个分布,我正在尝试恢复我指定的原始参数,但是,fit 方法返回不同的参数。
import numpy as np
import pandas as pd
from scipy.stats import rv_continuous
from scipy.special import erf
from scipy.special import erfinv
class lognorm_v2(rv_continuous):
def _pdf(self, x, mu, sigma):
return 1 / (x * sigma * np.sqrt(2 * np.pi)) * np.exp(-0.5 * ((np.log(x) - mu)/sigma)**2)
def _cdf(self, x, mu, sigma):
return 0.5 + 0.5 * erf((np.log(x) - mu)/ (np.sqrt(2)*sigma))
def _sf(self, x, mu, sigma):
u = (x)**b/(1+x**b)
return 1 - 0.5 + 0.5 * erf((np.log(x) - mu)/ (np.sqrt(2)*sigma))
def _ppf(self,x, mu, sigma):
return np.exp(sigma * erfinv(2*x - 1) - mu)
def _argcheck(self, mu, sigma):
s = sigma > 0
return s
np.random.seed(seed=111)
logn = lognorm_v2(name='lognorm_v2',a=0,b=np.inf)
test = logn.rvs(mu=2,sigma=1,loc=0,scale=1,size=100000)
logn.fit(test)
logn.fit(test,floc=0,fscale=1)
当loc和scale不固定时获取参数:
(0.9216388162274325,
0.7061876689651909,
-0.0003659266464081178,
0.05399544825451739)
修复后结果为:
(-2.0007136838780917, 0.7086144279779958, 0, 1)
为什么我无法提取原始模拟中指定的 mu 2 和 sigma 1?我知道我不会得到确切的值,但对于 100K 模拟,它们应该非常接近。
我的 numpy 是 1.19.2 版本,scipy 是 1.5.2。
谢谢!
我已经用正确的 _ppf 修正了代码,它似乎产生了适合 mu 和 sigma 的结果
代码,Python3.9Windows10x64
import numpy as np
from scipy.stats import rv_continuous
from scipy.special import erf
from scipy.special import erfinv
SQRT2 = np.float64(1.4142135623730951)
class lognorm_v2(rv_continuous):
def _pdf(self, x, μ, σ):
return 1 / (x * σ * SQRT2 * np.sqrt(np.pi)) * np.exp(-0.5 * ((np.log(x) - μ)/σ)**2)
def _cdf(self, x, μ, σ):
return 0.5 + 0.5 * erf((np.log(x) - μ)/ (SQRT2*σ))
def _ppf(self, x, μ, σ):
return np.exp(μ + σ * SQRT2 * erfinv(2.0*x - 1.0))
def _argcheck(self, μ, σ):
s = σ > 0.0
return s
np.random.seed(seed=111)
logn = lognorm_v2(name='lognorm_v2', a=0.0, b=np.inf)
test = logn.rvs(μ=2.0,σ=1.0,loc=0.0,scale=1.0, size=100000)
logn.fit(test,floc=0,fscale=1)
打印出来
(1.9990788106319746, 1.0021523463000124, 0, 1)
我已经使用自定义 scipy class 重新定义了对数正态分布。我已经模拟了这个分布,我正在尝试恢复我指定的原始参数,但是,fit 方法返回不同的参数。
import numpy as np
import pandas as pd
from scipy.stats import rv_continuous
from scipy.special import erf
from scipy.special import erfinv
class lognorm_v2(rv_continuous):
def _pdf(self, x, mu, sigma):
return 1 / (x * sigma * np.sqrt(2 * np.pi)) * np.exp(-0.5 * ((np.log(x) - mu)/sigma)**2)
def _cdf(self, x, mu, sigma):
return 0.5 + 0.5 * erf((np.log(x) - mu)/ (np.sqrt(2)*sigma))
def _sf(self, x, mu, sigma):
u = (x)**b/(1+x**b)
return 1 - 0.5 + 0.5 * erf((np.log(x) - mu)/ (np.sqrt(2)*sigma))
def _ppf(self,x, mu, sigma):
return np.exp(sigma * erfinv(2*x - 1) - mu)
def _argcheck(self, mu, sigma):
s = sigma > 0
return s
np.random.seed(seed=111)
logn = lognorm_v2(name='lognorm_v2',a=0,b=np.inf)
test = logn.rvs(mu=2,sigma=1,loc=0,scale=1,size=100000)
logn.fit(test)
logn.fit(test,floc=0,fscale=1)
当loc和scale不固定时获取参数:
(0.9216388162274325, 0.7061876689651909, -0.0003659266464081178, 0.05399544825451739)
修复后结果为:
(-2.0007136838780917, 0.7086144279779958, 0, 1)
为什么我无法提取原始模拟中指定的 mu 2 和 sigma 1?我知道我不会得到确切的值,但对于 100K 模拟,它们应该非常接近。 我的 numpy 是 1.19.2 版本,scipy 是 1.5.2。 谢谢!
我已经用正确的 _ppf 修正了代码,它似乎产生了适合 mu 和 sigma 的结果
代码,Python3.9Windows10x64
import numpy as np
from scipy.stats import rv_continuous
from scipy.special import erf
from scipy.special import erfinv
SQRT2 = np.float64(1.4142135623730951)
class lognorm_v2(rv_continuous):
def _pdf(self, x, μ, σ):
return 1 / (x * σ * SQRT2 * np.sqrt(np.pi)) * np.exp(-0.5 * ((np.log(x) - μ)/σ)**2)
def _cdf(self, x, μ, σ):
return 0.5 + 0.5 * erf((np.log(x) - μ)/ (SQRT2*σ))
def _ppf(self, x, μ, σ):
return np.exp(μ + σ * SQRT2 * erfinv(2.0*x - 1.0))
def _argcheck(self, μ, σ):
s = σ > 0.0
return s
np.random.seed(seed=111)
logn = lognorm_v2(name='lognorm_v2', a=0.0, b=np.inf)
test = logn.rvs(μ=2.0,σ=1.0,loc=0.0,scale=1.0, size=100000)
logn.fit(test,floc=0,fscale=1)
打印出来
(1.9990788106319746, 1.0021523463000124, 0, 1)