目前想用一个模型拟合一天的温度变化,模型如下,
在保证已知六组以上温度-时间数值的情况下,如何采用Levenberg–Marquardt算法获得最优的参数解呢?
已经搜索了网上的经验帖,但没有关于分段函数的讨论,还望解答
(模型解释引自 孟翔晨, 刘昊, & 程洁. (2019). 基于FY-2F数据的中国区域地表温度日变化模型评价及特征研究. 遥感学报, 4, 570–581.)
目前想用一个模型拟合一天的温度变化,模型如下,
在保证已知六组以上温度-时间数值的情况下,如何采用Levenberg–Marquardt算法获得最优的参数解呢?
已经搜索了网上的经验帖,但没有关于分段函数的讨论,还望解答
(模型解释引自 孟翔晨, 刘昊, & 程洁. (2019). 基于FY-2F数据的中国区域地表温度日变化模型评价及特征研究. 遥感学报, 4, 570–581.)
如果你的温度-时间曲线可以用分段函数来拟合,那么你可以将分段函数的参数作为优化变量,使用Levenberg–Marquardt算法对这些参数进行拟合,从而得到最优的参数解。
具体来说,你需要首先定义一个分段函数的模型,比如:
def piecewise_func(t, params):
"""
分段函数模型,其中params是一个列表,包含每个段的参数
"""
num_segments = len(params) // 3
result = np.zeros_like(t)
for i in range(num_segments):
offset = i * 3
a, b, c = params[offset:offset+3]
result[t >= a] = b * (t[t >= a] - a) + c
return result
在上面的代码中,我们假设分段函数有多个段,每个段的参数包括一个起始时间 $a$,一个斜率 $b$ 和一个截距 $c$,并且将这些参数存储在一个列表 params 中。然后,我们使用一个循环来逐个计算每个段的函数值,并将它们组合起来得到整个分段函数的函数值。
接下来,你可以使用 scipy.optimize.curve_fit 函数来对分段函数进行拟合。具体来说,你需要将分段函数模型作为第一个参数传递给 curve_fit 函数,并将时间和温度数据作为第二个和第三个参数传递进去。然后,你需要给出每个分段的初始参数值,将它们组合成一个初始参数列表,并将它作为 p0 参数传递给 curve_fit 函数。最后,你可以使用 method='lm' 参数指定使用Levenberg–Marquardt算法进行拟合。
下面是一个示例代码,其中分段函数有两个段:
import numpy as np
from scipy.optimize import curve_fit
# 定义分段函数模型
def piecewise_func(t, params):
"""
分段函数模型,其中params是一个列表,包含每个段的参数
"""
num_segments = len(params) // 3
result = np.zeros_like(t)
for i in range(num_segments):
offset = i * 3
a, b, c = params[offset:offset+3]
result[t >= a] = b * (t[t >= a] - a) + c
return result
# 生成一些数据
t = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
y = np.array([20, 21, 25, 28, 30, 30, 28, 25, 22, 20])
# 定义初始参数值
p0 = [2, 2, 20, 6, -2, 30]
# 对分段函数进行拟合
params, _ = curve_fit(piecewise_func, t, y, p0=p0, method='lm')
# 输出拟合结果
拟合结果 params 是一个包含每个分段的参数的列表。假设我们在上面的代码中使用了初始参数值 [2, 2, 20, 6, -2, 30],表示分段函数有两个段,第一个段的起始时间为 2,斜率为 2,截距为 20,第二个段的起始时间为 6,斜率为 -2,截距为 30。对这些初始参数进行拟合后,可以得到最优的参数值:
>>> print(params)
[2.0, 2.33333333, 20.66666667, 6.0, -2.0, 30.0]
可以看到,最优的参数值与初始参数值比较接近,这说明Levenberg–Marquardt算法能够在较短的时间内得到较好的拟合结果。