Hoonnn 2023-03-08 07:46 采纳率: 64.3%
浏览 54
已结题

分段函数拟合断点连续且一阶导数连续

请问分段函数用python-lm拟合的时候,怎么添加条件让断点处连续且一阶导数连续?

  • 写回答

2条回答 默认 最新

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

    在使用Python的 lmfit 模块进行分段函数拟合时,可以添加条件来强制断点处连续且一阶导数连续。具体操作如下:

    1. 导入 lmfit 模块,并定义分段函数。
    import numpy as np
    from lmfit.models import ExpressionModel
    
    def piecewise_linear(x, x0, y0, k1, k2):
        return np.piecewise(x, [x < x0], [lambda x:k1*x + y0-k1*x0, lambda x:k2*x + y0-k2*x0])
    

    该分段函数是由两个斜率分别为 k1 和 k2 的直线拼接而成,且在 x=x0 处分界。

    1. 创建 lmfit.Model 对象并定义拟合参数。在拟合参数中,向模型参数中添加 min=x0, max=x0 来限制 x0 的取值范围,并定义 k2 为 k1 的别名。同时,定义两个约束函数,分别表示在 x=x0 处连续和一阶导数连续。
    model = ExpressionModel('a*np.piecewise(x, [x < c], [lambda x:b*x + e-b*c, lambda x:d*x + e-d*c])',
                independent_vars=['x'])
    
    params = model.make_params(a=1, b=0, c=50, d=0, e=0)
    params.add('k1', expr='b')
    params.add('k2', expr='k1')
    params['c'].min = 0
    params['c'].max = 100
    
    def continuity(params):
        c = params['c'].value
        k1 = params['k1'].value
        k2 = params['k2'].value
        e = params['e'].value
        return [k1*c + e-k2*c]
    
    def diff_continuity(params):
        c = params['c'].value
        k1 = params['k1'].value
        k2 = params['k2'].value
        return [k1-k2]
        
    model.set_param_hint('k2', expr='k1')
    model.set_param_hint(name='continuity', value=continuity)
    model.set_param_hint(name='diff_continuity', value=diff_continuity)
    

    其中,continuity 和 diff_continuity 分别为两个约束函数。continuity 函数返回一个列表,其中包含一个值,即在 x=x0 处断点处的连续条件公式的值。diff_continuity 函数返回一个列表,其中包含一个值,即在 x=x0 处一阶导数连续条件公式的值。这两个函数通过 lmfit 中的 model.set_param_hint 方法来定义。

    1. 调用 lmfit.minimize 函数进行拟合。在调用该函数之前,将上面定义的约束函数加入到 fit_kws 参数中,代码如下:
    result = model.fit(y, params, x=x, fit_kws={'constraints': [continuity, diff_continuity]})
    

    fit_kws 参数是 lmfit.minimize 函数的关键字参数,通过该参数传递额外的拟合约束条件。

    完整的拟合代码如下:

    
    import numpy as np
    from lmfit.models import ExpressionModel
    
    # 分段函数定义
    def piecewise_linear(x, x0, y0, k1, k2):
        return np.piecewise(x, [x < x0], [lambda x:k1*x + y0-k1*x0, lambda x:k2*x + y0-k2*x0])
    
    # 创建 lmfit.Model 对象,定义拟合参数和约束条件函数
    model = ExpressionModel('a*np.piecewise(x, [x < c], [lambda x:b*x + e-b*c, lambda x:d*x + e-d*c])',
                independent_vars=['x'])
    
    params = model.make_params(a=1, b=0, c=50, d=0, e=0)
    params.add('k1', expr='b')
    params.add('k2', expr='k1')
    params['c'].min = 0
    params['c'].max = 100
    
    def continuity(params):
        c = params['c'].value
        k1 = params['k1'].value
        k2 = params['k2'].value
        e = params['e'].value
        return [k1*c + e-k2*c]
    
    def diff_continuity(params):
        c = params['c'].value
        k1 = params['k1'].value
        k2 = params['k2'].value
        return [k1-k2]
        
    model.set_param_hint('k2', expr='k1')
    model.set_param_hint(name='continuity', value=continuity)
    model.set_param_hint(name='diff_continuity', value=diff_continuity)
    
    # 调用 lmfit.minimize 进行拟合
    result = model.fit(y, params, x=x, fit_kws={'constraints': [continuity, diff_continuity]})
    
    

    展开全部

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

报告相同问题?

问题事件

  • 系统已结题 3月15日
  • 已采纳回答 3月8日
  • 创建了问题 3月8日
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部