问题
I have data sets that I would like to fit to two equations:
y1 = a1 + a2 * T / 2 + a3 * T^2 / 3 + a4 * T^3 / 4 + a5 * T^4 / 5 + a6 / T
y2 = a1 * lnT + a2 * T + a3 * T^2 / 2 + a4 * T^3 / 3 + a5 * T^4 / 4 + a7
The two polynomials share some parameters (a1 through a5) so I would like to fit these two equations simultaneously.
I tried to do it with scipy.optimize.curve_fit:
import numpy as np
from scipy.optimize import curve_fit
def func(T, a1, a2, a3, a4, a5, a6, a7):
y1 = a1 + a2 * T / 2 + a3 * T**2 / 3 + a4 * T**3 / 4 + a5 * T**4/5 + a6/T
y2 = a1*np.log(T) + a2*T + a3 * T**2/2 + a4 * T**3/4 + a5 * T**4/4 + a7
return np.stack((y1, y2), axis = 1)
T = np.linspace(300, 1000, 20)
ydata_1 = np.array([
0.02139265, 0.40022353, 0.70653103, 0.95896469, 1.17025634,
1.34944655, 1.50316659, 1.63641239, 1.75303086, 1.85603601,
1.94782051, 2.03030092, 2.10501971, 2.17321829, 2.23589026,
2.29382086, 2.34761661, 2.39772787, 2.44446625, 2.48801814])
ydata_2 = np.array([
15.73868267, 16.14232408, 16.50633034, 16.83724622,
17.14016153, 17.41914701, 17.67752993, 17.91807535,
18.14310926, 18.35460465, 18.55424316, 18.74346017,
18.92347836, 19.09533317, 19.25989235, 19.41787118,
19.56984452, 19.71625632, 19.85742738, 19.99356154])
ydata = np.stack((ydata_1, ydata_2), axis = 1)
popt, pconv = curve_fit(f = func, xdata = T, ydata = ydata)
However I get the error:
minpack.error: Result from function call is not a proper array of floats.
I am not even sure if this is the right approach to solve the problem.
回答1:
You can try minimising the L_2 norm (i.e. least squares fitting) in a 2 dimensional space for your y-values:
from scipy.optimize import minimize
def func(params):
a1, a2, a3, a4, a5, a6, a7 = params
y1 = a1 + a2 * T / 2 + a3 * T**2 / 3 + a4 * T**3 / 4 + a5 * T**4/5 + a6/T
y2 = a1*np.log(T) + a2*T + a3 * T**2/2 + a4 * T**3/4 + a5 * T**4/4 + a7
return np.sum((y1 - ydata_1) ** 2 + (y2 - ydata_2) ** 2)
T = np.linspace(300, 1000, 20)
ydata_1 = np.array([
0.02139265, 0.40022353, 0.70653103, 0.95896469, 1.17025634,
1.34944655, 1.50316659, 1.63641239, 1.75303086, 1.85603601,
1.94782051, 2.03030092, 2.10501971, 2.17321829, 2.23589026,
2.29382086, 2.34761661, 2.39772787, 2.44446625, 2.48801814])
ydata_2 = np.array([
15.73868267, 16.14232408, 16.50633034, 16.83724622,
17.14016153, 17.41914701, 17.67752993, 17.91807535,
18.14310926, 18.35460465, 18.55424316, 18.74346017,
18.92347836, 19.09533317, 19.25989235, 19.41787118,
19.56984452, 19.71625632, 19.85742738, 19.99356154])
# choose reasonable values for your 7 parameters here,
# i.e. close to the "right" answer, this may take a few tries
first_guess = [a1_0, a2_0, a3_0, a4_0, a5_0, a6_0, a7_0]
# here we run the minimisation
res = minimize(func, first_guess)
# this is an array of your best fit values for a1-a7
best_fit = res.x
However, it seems that @Stelios is right in that you will have a hard time getting a good fit with your particular model.
回答2:
(extended comment)
a) curve_fit
is used to fit a single function based on a single dataset. In your case, you have two functions to fit based on two datasets. This requires in principle setting up an optimization problem from scratch, i.e., define a single objective function (with or without constraints). The objective function could, for example, be the sum of the squared residual errors of both fits. You would then use an optimization solver such as scipy.optimimize.minimize
to find the optimal variables.
b) Your model (fitting functions) will probably introduce numerical difficulties in the optimization. For example, variables a5
and a6
for y1
are factors for T**4
and 1/T
respectively, which, for T=10**3
correspond to values of 10**12
and 10**-3
. This is a huge scale difference, close to the hardware precision, which suggests to me that you should reconsider your model.
来源:https://stackoverflow.com/questions/41090791/how-do-i-optimize-and-find-the-coefficients-for-two-equations-simultaneously-in