如何使scipy适合log(a-x)类型的函数.curve_fit? [英] How to fit log(a-x) type functions with scipy. curve_fit?

查看:70
本文介绍了如何使scipy适合log(a-x)类型的函数.curve_fit?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试拟合一个看起来像 log(y)= a * log(bx)+ c 的函数,其中 a b c 是需要拟合的参数.相关的代码是

I am trying to fit a function which looks like log(y)=a*log(b-x)+c, where a, b and c are the parameters that need to be fitted. The relevant bit of code is

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

def logfunc(T, a, b, c):
    v=(a*np.log(b-T))+c
    return v

popt, pcov=curve_fit(logfunc, T, np.log(Energy), check_finite=False, bounds=([0.1, 1.8, 0.1], [1.0, 2.6, 1.0]))

plt.plot(T, logfunc(T, *popt))
plt.show

其中 T Energy 是一些生成的数据(我用它来绘制其他内容,因此数据应该没问题). T 在0.3到3.2之间.我很确定问题出在某个地方,因为我不断收到错误 ValueError:残差在起始点不是有限的.但我不确定该如何解决.

Where T and Energy is some data that was generated (I use it to plot other things so the data should be fine). T is between 0.3 and 3.2. I am pretty sure that the problem is the fact that there is a point where b=T because I keep getting the error ValueError: Residuals are not finite in the initial point. but I am not sure how to solve this.

推荐答案

您可能会找到 lmfit 包(

You may find the lmfit package (http://lmfit.github.io/lmfit-py/) useful for this sort of problem. This provides a higher-level approach to curve fitting problems and a better abstraction of Parameters and Models than scipy.optimize package or curve_fit() function.

对于这里的问题, lmfit 的两个重要功能是

For the problem here, two important features of lmfit are

  1. 设置变量界限的能力. curve_fit()也可以做到这一点,但是只能通过处理最小/最大范围的有序列表来实现.使用 lmfit ,边界属于Parameter对象.
  2. 具有一种显式设置用于处理NaN值的策略的方法,这肯定会导致您的健康状况出现问题.
  1. the ability to set bounds on variables. curve_fit() can do this as well, but only by working with ordered lists of min/max bounds. With lmfit, the bounds belong to Parameter objects.
  2. having a way to explicitly set a policy for handling NaN values, which could definitely cause problems for your fit.

使用lmfit,您的脚本的编写大致为

With lmfit, your script would be written approximately as

import numpy as np
import matplotlib.pyplot as plt
from lmfit import Model

def logfunc(T, a, b, c):
    return (a*np.log(b-T))+c

log_model = Model(logfunc, nan_policy='raise')  # raise error on NaNs
params = log_model.make_params(a=0.5, b=2.0, c=0.5) # initial values
params['b'].min = 1.8  # set min/max values
params['b'].max = 2.6 
params['c'].min = 0.1  # and so forth 

result = log_model.fit(np.log(Energy), params, T=T)

print(result.fit_report())

plt.plot(T, Energy, 'bo', label='data')
plt.plot(T, np.exp(result.best_fit), 'r--', label='fit')
plt.legend()
plt.xlabel('T')
plt.ylabel('Energy')
plt.gca().set_yscale('log', basey=10)
plt.show()

这比您的开始脚本稍微冗长,这是因为它提供了标记的图,并且因为使用Parameter对象而不是标量可以提供更大的灵活性和清晰度.

This is slightly more verbose than your starting script because it gives a labeled plot and because using Parameter objects instead of scalars gives more flexibility and clarity.

为了适合自己,您可以考虑将 nan_policy 设置为忽略",这会在出现NaN时将其忽略掉-绝不是一个好主意,但有时有助于您开始找到 log(bT)有效.您还可以更改模型功能以进行类似的操作

For your fit, you might consider setting the nan_policy to 'omit', which will omit NaNs as they occur -- never a great idea, but sometimes helpful to get you started on finding where log(b-T) is valid. You could also alter your model function to do something like

def logfunc(T, a, b, c):
    arg = b - T
    arg[np.where(arg < 1.e-16)] = 1.e-16
    return a*np.log(arg) + c

要明确预防NaN的一个明显原因.

To explicitly prevent one obvious cause of NaNs.

这篇关于如何使scipy适合log(a-x)类型的函数.curve_fit?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆