微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在 Python Curve_fit 上设置两个参数之间的不等式?

如何解决如何在 Python Curve_fit 上设置两个参数之间的不等式?

所以,我正在编写一个程序来将 5 参数函数 (s,t,k,h,b) 拟合到一组实验数据中。好吧,该程序有效,但我需要满足一个条件:0

算法是:

import xlrd
import numpy
import math
import scipy
from scipy.optimize import curve_fit
workbook = xlrd.open_workbook('Pasta3.xls')
sheet = workbook.sheet_by_name('teste')
x = []
for i in range (18):
    cell = sheet.cell_value(i+1,1)
    x.append(cell)
y = []
for i in range (18):
    cell_=sheet.cell_value(i+1,0)
    y.append(cell_)

def Re(x,s,b):
    return 130 + ((38000-130)*(1+s*((2*math.pi*x*t)**(-1*k))*math.cos(k*math.pi/2)+   ((2*math.pi*x*t)**(-1*h))*math.cos(h*math.pi/2)))/((((38000-130)*(1+s*((2*math.pi*x*t)**(-1*k))*math.cos(k*math.pi/2)+((2*math.pi*x*t)**(-1*h))*math.cos(h*math.pi/2)))/(38000-130))**2+(((38000-130)*(s*((2*math.pi*x*t)**(-1*k))*math.sin(k*math.pi/2)+((2*math.pi*x*t)**(-1*h))*math.sin(h*math.pi/2)+((2*math.pi*x*t*b)**(-1))))/(38000-130))**2)
popt,_ = curve_fit(Re,x,y)
print(popt)

解决方法

添加不等式约束的一种方法是使用 lmfit 库。它的特点之一是能够将约束强加为数学表达式。结合简单的上下界,允许不等式约束。

对于您的示例,转换为使用 lmfit(可能还需要进行一些清理以确保所有内容都是 numpy ndarray)会得到如下结果:

import xlrd
from numpy import array,pi,sin,cos
from lmfit import Model

workbook = xlrd.open_workbook('Pasta3.xls')
sheet = workbook.sheet_by_name('teste')
x = []
for i in range (18):
    cell = sheet.cell_value(i+1,1)
    x.append(cell)
y = []
for i in range (18):
    cell_=sheet.cell_value(i+1,0)
    y.append(cell_)

x = array(x)
y = array(y)

def Re(x,s,t,k,h,b):
    xt = 2*pi*xt
    sxtk = s*xt**(-k)
    xth = xt**(-h)
    scale= 38000-130

    term1  = 1 + sxtk*cos(k*pi/2) + xth*cos(h*pi/2)
    term2 = sxtk*sin(k*pi/2) + xth*sin(h*pi/2)+(1/(xt*b))

    return 130 + scale**2 * term1/ (term1 + term2)

model = lmfit.Model(Re)
params = model.make_params(s=0.5,t=0.5,k=0.2,h=0.5,b=0.5)

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

print(result.fit_report())

一些重要的注意事项:

  1. 可读性很重要。真的,它比什么都重要,这就是您选择 Python 的原因。没有人 - 包括你 - 会理解你的拟合功能的混乱。这让它完全没用:即使它非常合身,你也不会知道它做了什么。我做了一些重构和简化,但你当然想检查一下。

  2. 你的例子没有给出拟合参数的初始值。 scipy.optimize.curve_fit() 默默地允许这样做,为所有参数提供 1 的值。这是一个可怕的错误功能,会给许多用户带来麻烦。是的,这似乎是额外的工作,但拟合方法需要初始值。您始终需要提供对您的数据有意义的初始值。没有例外。

在带有 lmfit 的示例中,为每个参数设置了初始值。此处,它们都设置为 0 到 1 之间的值,但您需要将它们设置为数据的合理初始值。

要设置参数的界限,你可以这样做

params['k'].min = 0
params['k'].max = 1

等等。要说h > k,您需要定义一个新参数——我将其命名为h_minus_k,然后使用数学表达式将h 设置为从该值和{{ 1}}:

k

现在,由于 params.add('h_minus_k',value=0.1,min=0,max=1) params['h'].expr = 'k + h_minus_k' 不能为负,h_minus_k 将被保留。拟合中仍有 5 个变量,现在是 h>kstkbh_minus_k 将在拟合中变化,但不能自由变化——它的值受 hk 的值约束。有了这个约束,你可以再次尝试拟合并比较结果:

h_minus_k

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。