【问题标题】:How to fit data with Log normal CDF如何用 Log normal CDF 拟合数据
【发布时间】:2019-05-16 21:09:36
【问题描述】:

我是 Python 的新用户,我正在尝试用 CDF 拟合一些实验数据。数据如下,应以 x 轴对数刻度绘制:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

x=np.array([0.995, 3.003, 5.908, 10.525, 13.617, 24.321, 33.917, 47.843, 64.172, 91.353, 126.745, 174.118, 225.059, 292.998, 369.133, 640.295, 828.169, 1255.39, 1496.613, 1942.785])

y=np.array([0.142, 0.2, 0.25, 0.36, 0.498, 0.616, 0.599, 0.7, 0.835, 1.102, 1.083, 1.225, 1.133, 1.165, 1.298, 1.365, 1.298, 1.373, 1.409, 1.538])

pyplot.xscale('log')

plt.plot(x,y,'r.')

我找到了一位用户的证词,该用户使用以下方法拟合了数据:

from scipy.special import erf
from lmfit import Model

def gaussian_cdf(x,amp,mu,sigma):
    return (amp/2.0)*(1+erf((mu-x)/(sigma*np.sqrt(2.0))))


model = Model(gaussian_cdf,prefix='g1_') + Model(gaussian_cdf,prefix='g2_')

params = model.make_params(g1_amp=0.50,g1_mu=94,g1_sigma=1.,
                          g2_amp=0.50,g2_mu=98,g2_sigma=1.)

params['g1_sigma'].min=0
params['g2_sigma'].min=0

result = model.fit(y,params,x = x)

print(result.fit_report())

comps=result.eval_components(result.params,x=x)


plt.plot(x,y,'r.',label='data')
plt.plot(x,result.best_fit,'k-',label='fit')
plt.plot(x,comps['g1_'],'b--',label='g1_')
plt.plot(x,comps['g2_'],'g--',label='g2_')
plt.legend()
plt.show()

enter image description here

但是当我尝试将此代码修改为我自己的问题(其数据如上所示)处理 LogNormal 分布 pdf 和 cdf 时,结果并不好。

enter image description here

如果有人可以帮助我,我将不胜感激!

提前致谢

【问题讨论】:

  • 您发布的代码看起来像是一个很好的示例,但您并没有发布您使用的实际代码。这使得很难知道出了什么问题。贴出你实际运行的代码。
  • 嗨,M 纽维尔。感谢您的反馈意见。我使用了完全相同的代码,但我使用 np.log(x) 代替 x 来计算对数正态分布。但结果是第二个图中显示的
  • log(x)?还是您的意思是将 log(y) 放入 cdf 的日志中? FWIW,这就是为什么发布您实际使用的代码很有帮助的原因,特别是与有效但不是您使用的代码相比。您的代码为什么不起作用的答案可能在这种差异中找到。但我们不知道这种区别是什么。
  • 在相关说明中,np.log 是自然对数,np.log10 是基于 10 的对数。
  • 您的意思是要为您的数据拟合一个log-normal 分布函数吗?因为在我看来,你的数据不是这样的。

标签: python data-fitting cdf


【解决方案1】:

您可以通过使用scipy.optimize.curve_fit 并定义您的对数函数来拟合 y = a * log10(b * x + h) + k 形式的行(这似乎比对数正态分布更适合您的数据) .

import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import lognorm
from scipy.optimize import curve_fit

x=np.array([0.995, 3.003, 5.908, 10.525, 13.617, 24.321, 33.917, 47.843, 64.172, 91.353, 126.745, 174.118, 225.059, 292.998, 369.133, 640.295, 828.169, 1255.39, 1496.613, 1942.785])

y=np.array([0.142, 0.2, 0.25, 0.36, 0.498, 0.616, 0.599, 0.7, 0.835, 1.102, 1.083, 1.225, 1.133, 1.165, 1.298, 1.365, 1.298, 1.373, 1.409, 1.538])

def log(x, a, b, h, k):
    return a*np.log10(b*x + h) + k

# Provide guesses to the parameters
params = [6, 1, 0, 0]#, .2]
popt, pcov = curve_fit(log, x, y, p0=params)

plt.plot(x,y,'r.')
plt.plot(x, log(x, *popt), 'k--', label = 'fit: a = %.2f b = %.2f h = %.2f k = %.2f ' 
% tuple(popt)) #locl = %.2f scale = %.2f
plt.legend(loc = 'lower right')
#plt.xscale('log')
plt.show()

没有对数刻度,你会得到看起来像这样的拟合

使用对数比例,您的身材看起来像

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-26
    相关资源
    最近更新 更多