Hoonnn 2022-05-23 17:38 采纳率: 64.3%
浏览 30
已结题

请教采用Levenberg–Marquardt算法求非线性分段函数的参数

目前想用一个模型拟合一天的温度变化,模型如下,

img

在保证已知六组以上温度-时间数值的情况下,如何采用Levenberg–Marquardt算法获得最优的参数解呢?
已经搜索了网上的经验帖,但没有关于分段函数的讨论,还望解答

(模型解释引自 孟翔晨, 刘昊, & 程洁. (2019). 基于FY-2F数据的中国区域地表温度日变化模型评价及特征研究. 遥感学报, 4, 570–581.)

  • 写回答

2条回答 默认 最新

  • 陈书予 2023年6月份城市(北京)之星TOP 1 2023-03-04 18:11
    关注

    如果你的温度-时间曲线可以用分段函数来拟合,那么你可以将分段函数的参数作为优化变量,使用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算法能够在较短的时间内得到较好的拟合结果。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 3月12日
  • 已采纳回答 3月4日
  • 创建了问题 5月23日

悬赏问题

  • ¥15 x趋于0时tanx-sinx极限可以拆开算吗
  • ¥500 把面具戴到人脸上,请大家贡献智慧
  • ¥15 任意一个散点图自己下载其js脚本文件并做成独立的案例页面,不要作在线的,要离线状态。
  • ¥15 各位 帮我看看如何写代码,打出来的图形要和如下图呈现的一样,急
  • ¥30 c#打开word开启修订并实时显示批注
  • ¥15 如何解决ldsc的这条报错/index error
  • ¥15 VS2022+WDK驱动开发环境
  • ¥30 关于#java#的问题,请各位专家解答!
  • ¥30 vue+element根据数据循环生成多个table,如何实现最后一列 平均分合并
  • ¥20 pcf8563时钟芯片不启振