如何解决使用curve_fit估计不同大小数据集上的通用模型参数
我正在研究曲线拟合问题,我打算在几个大小不等的数据集上全局估计共享模型参数。我从下面链接中的代码开始工作,其中线性回归 y = a*x + b 的公共 a 参数是在具有公共 x 向量的三个不同 y 向量上估计的。 How to use curve_fit from scipy.optimize with a shared fit parameter across multiple datasets?
我设法使代码示例适应更一般的情况,使用三个不同的 x 向量,一个对应于每个 y 数据向量。但是,当我想进一步扩展它以适用于大小不等的数据集时,我遇到了以下错误:“ValueError:使用序列设置数组元素。”。
请在下面找到代码示例。非常感谢任何帮助!
干杯
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
x = [[0,1,2,3],[0.2,1.2,2.2,3.2],[0.3,1.3,2.3]]
y = [[-0.80216234,1.41125365,1.42565202,2.42567754],[ 1.34166743,1.29731851,2.98374731,3.32110875],[ 1.71398203,3.29737756,3.81456949]]
x = np.array(x)
y = np.array(y)
def f(x,a,b):
return a * x + b
def g(x,b_1,b_2,b_3):
return np.concatenate((f(x[0],b_1),f(x[1],b_2),f(x[2],b_3)))
(a,*b),_ = curve_fit(g,x,y.ravel())
for x_i,y_i,b_i in zip(x,y,b):
plt.plot(x_i,f(x_i,b_i),label=f"{a:.1f}x{b_i:+.1f}")
plt.plot(x_i,linestyle="",marker="x",color=plt.gca().lines[-1].get_color())
plt.legend()
plt.show()
有关具有多个相同大小的 x 向量的工作示例的代码,请参见下文:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
x = [[0,2.3,3.3]]
y = [[-0.80216234,3.81456949,4.25]]
x = np.array(x)
y = np.array(y)
def f(x,b_3):
return np.concatenate((f(x[0],b):
plt.plot(x_i,label=f"{a:.1f}x{b_i:+.1f}")
plt.plot(x_i,color=plt.gca().lines[-1].get_color())
plt.legend()
plt.show()
解决方法
问题是您无法从参差不齐的列表中创建 numpy.array
。要重新转换为 np.array
,所有维度都必须匹配,即您不能有一个空的 column 条目,因为这对 Numpy 没有意义。
在您的情况下,您还没有为数组中的 列 之一定义条目(即最后 行 中的 3 个条目,而其他 行 em> 有 4 个条目)。 Numpy 根本不会让你这样做,因为它是一个数值包,它依赖于矩形良好定义的数组来进行计算。
,总的来说,我同意最小二乘拟合的含义相当复杂......一些快速思考:
- 如果从不同长度的数据集中估计得到的
b
参数,你能确定它们同样有效吗? - 您获得的 b 参数越多,它们的估计就越不确定,因为您只优化组合拟合性能而不是每个单独的拟合性能
- 我也不确定雅可比的数值计算在这种情况下的效果如何...可能值得实现一个自定义的
jac
函数,以精确的方式计算雅可比 - ... anad 我确定还有更多我目前不知道的问题 :D
尽管如此,您当然可以欺骗scipy.optimize
做您想做的事...
但是,您必须更深入一步,直接使用 scipy.optimize.least_squares
而不是使用更高级别的 scipy.optimize.curve_fit
函数。
通过这种方式,您可以改变残差的计算方式,以接受不同长度的数据集。
...这是它如何工作的一个快速而肮脏的实现:
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import least_squares
x = [[0.0,1.0,2.0,3.0,4.0,5.0],[0.2,1.2,2.2,3.2],[0.3,1.3,2.3 ]]
y = [[-0.80216234,1.41125365,1.42565202,2.42567754,3,4],[ 1.34166743,1.29731851,2.98374731,3.32110875],[ 1.71398203,3.29737756,3.81456949 ]]
def f(x,a,b):
return a * x + b
def fun(parameters):
# separate a and b parameters
a,*b = parameters
# calculate function-results based on a shared a- and variable b- parameters
res = (f(xi,bi) for (xi,bi) in zip(map(np.array,x),b))
# calculate the residuals
errs = []
for i,j in zip(res,map(np.array,y)):
errs += (i - j).tolist()
return np.array(errs)
# set start-values
start_values = (1,1,2,3)
# do the fit
a,*b = least_squares(fun,start_values).x
for x_i,y_i,b_i in zip(map(np.array,y,b):
plt.plot(x_i,f(x_i,b_i),label=f"{a:.1f}x{b_i:+.1f}")
plt.plot(x_i,linestyle="",marker="x",color=plt.gca().lines[-1].get_color())
plt.legend()
plt.show()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。