Python 曲线拟合多变量
Python curve fit multiple variable
我正在尝试用多个变量拟合一个函数,我的 fit_function return 有两个值,我需要找到适合这两个值的最佳参数。
这里是示例代码
import numpy as np
from scipy.optimize import curve_fit
# Fit function returns two values
def func(X, a, b, c):
x,y = X
val1 = np.log(a) + b*np.log(x) + c*np.log(y)
val2 = np.log(a)-4*val1/3
return (val1,val2)
# some artificially noisy data to fit
x = np.linspace(0.1,1.1,101)
y = np.linspace(1.,2., 101)
a, b, c = 10., 4., 6.
z ,v = func((x,y), a, b, c) * 1 + np.random.random(101) / 100
# initial guesses for a,b,c:
p0 = 8., 2., 7.
curve_fit(func, (x,y), (z,v), p0)
它适用于一个 return 值的 fitfunction,但不适用于两个。它给出:N=3 不得超过 M=2 错误。
if n > m:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
Improper input: N=3 must not exceed M=2
我需要找到同时最小化 val1 - z
和 val2- v
之间的残差的参数。
我在这里缺少什么?
这是我的输入数据的样子。
我需要适合 z/x 和 v/x 的参数。
scipy.optimize.curve_fit 通过比较 func 的参数列表 (a,b,c) 的长度 3 与因变量的长度来检查是否至少有与拟合参数一样多的数据点(z,v) as 2。是的,z和v都有三个以上的数据点,但是(z,v)的长度是两个。
根据其他人的观察,您的函数需要 return 具有输入数据形状的东西,因此您需要更改误差函数的输出形状。由于 scipy
执行最小二乘函数,因此可以通过使您的函数 return np.sqrt(val1 ** 2 + val2 ** 2)
.
但是,对于这类问题,我更喜欢使用我编写的 scipy
包装器来简化处理多个组件的过程,称为 symfit
。
在symfit
中,这个示例问题将解决如下:
from symfit import parameters, variables, log, Fit, Model
import numpy as np
import matplotlib.pyplot as plt
x, y, z1, z2 = variables('x, y, z1, z2')
a, b, c = parameters('a, b, c')
z1_component = log(a) + b * log(x) + c * log(y)
model_dict = {
z1: z1_component,
z2: log(a) - 4 * z1_component/3
}
model = Model(model_dict)
print(model)
# Make example data
xdata = np.linspace(0.1, 1.1, 101)
ydata = np.linspace(1.0, 2.0, 101)
z1data, z2data = model(x=xdata, y=ydata, a=10., b=4., c=6.) + np.random.random(101)
# Define a Fit object for this model and data. Demand a > 0.
a.min = 0.0
fit = Fit(model_dict, x=xdata, y=ydata, z1=z1data, z2=z2data)
fit_result = fit.execute()
print(fit_result)
# Make a plot of the result
plt.scatter(xdata, z1data, s=1, color='blue')
plt.scatter(xdata, z2data, s=1, color='green')
plt.plot(xdata, model(x=xdata, y=ydata, **fit_result.params).z1, color='blue')
plt.plot(xdata, model(x=xdata, y=ydata, **fit_result.params).z2, color='green')
输出:
z1(x, y; a, b, c) = b*log(x) + c*log(y) + log(a)
z2(x, y; a, b, c) = -4*b*log(x)/3 - 4*c*log(y)/3 - log(a)/3
Parameter Value Standard Deviation
a 2.859766e+01 1.274881e+00
b 4.322182e+00 2.252947e-02
c 5.008192e+00 5.497656e-02
Fitting status message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'
Number of iterations: 23
Regression Coefficient: 0.9961974241602712
我正在尝试用多个变量拟合一个函数,我的 fit_function return 有两个值,我需要找到适合这两个值的最佳参数。
这里是示例代码
import numpy as np
from scipy.optimize import curve_fit
# Fit function returns two values
def func(X, a, b, c):
x,y = X
val1 = np.log(a) + b*np.log(x) + c*np.log(y)
val2 = np.log(a)-4*val1/3
return (val1,val2)
# some artificially noisy data to fit
x = np.linspace(0.1,1.1,101)
y = np.linspace(1.,2., 101)
a, b, c = 10., 4., 6.
z ,v = func((x,y), a, b, c) * 1 + np.random.random(101) / 100
# initial guesses for a,b,c:
p0 = 8., 2., 7.
curve_fit(func, (x,y), (z,v), p0)
它适用于一个 return 值的 fitfunction,但不适用于两个。它给出:N=3 不得超过 M=2 错误。
if n > m:
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n, m))
Improper input: N=3 must not exceed M=2
我需要找到同时最小化 val1 - z
和 val2- v
之间的残差的参数。
我在这里缺少什么?
这是我的输入数据的样子。
我需要适合 z/x 和 v/x 的参数。
scipy.optimize.curve_fit 通过比较 func 的参数列表 (a,b,c) 的长度 3 与因变量的长度来检查是否至少有与拟合参数一样多的数据点(z,v) as 2。是的,z和v都有三个以上的数据点,但是(z,v)的长度是两个。
根据其他人的观察,您的函数需要 return 具有输入数据形状的东西,因此您需要更改误差函数的输出形状。由于 scipy
执行最小二乘函数,因此可以通过使您的函数 return np.sqrt(val1 ** 2 + val2 ** 2)
.
但是,对于这类问题,我更喜欢使用我编写的 scipy
包装器来简化处理多个组件的过程,称为 symfit
。
在symfit
中,这个示例问题将解决如下:
from symfit import parameters, variables, log, Fit, Model
import numpy as np
import matplotlib.pyplot as plt
x, y, z1, z2 = variables('x, y, z1, z2')
a, b, c = parameters('a, b, c')
z1_component = log(a) + b * log(x) + c * log(y)
model_dict = {
z1: z1_component,
z2: log(a) - 4 * z1_component/3
}
model = Model(model_dict)
print(model)
# Make example data
xdata = np.linspace(0.1, 1.1, 101)
ydata = np.linspace(1.0, 2.0, 101)
z1data, z2data = model(x=xdata, y=ydata, a=10., b=4., c=6.) + np.random.random(101)
# Define a Fit object for this model and data. Demand a > 0.
a.min = 0.0
fit = Fit(model_dict, x=xdata, y=ydata, z1=z1data, z2=z2data)
fit_result = fit.execute()
print(fit_result)
# Make a plot of the result
plt.scatter(xdata, z1data, s=1, color='blue')
plt.scatter(xdata, z2data, s=1, color='green')
plt.plot(xdata, model(x=xdata, y=ydata, **fit_result.params).z1, color='blue')
plt.plot(xdata, model(x=xdata, y=ydata, **fit_result.params).z2, color='green')
输出:
z1(x, y; a, b, c) = b*log(x) + c*log(y) + log(a)
z2(x, y; a, b, c) = -4*b*log(x)/3 - 4*c*log(y)/3 - log(a)/3
Parameter Value Standard Deviation
a 2.859766e+01 1.274881e+00
b 4.322182e+00 2.252947e-02
c 5.008192e+00 5.497656e-02
Fitting status message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'
Number of iterations: 23
Regression Coefficient: 0.9961974241602712