如何在LMFIT中约束指定表达式恒等于0
LMFIT实现两个向量点积恒为0的约束方案
你目前的写法只是创建了一个会随分量参数动态计算点积值的派生参数,没有添加约束逻辑,有三种常用方案可以实现点积始终为0的要求:
方案1:残差函数加惩罚项(最通用)
不需要额外定义a0dotn0参数,直接在拟合用的残差函数中加入点积的惩罚项即可,拟合过程会自动压低该值趋近于0:
def residual(params, x, data): # 提取各分量参数 n0_x = params['n0_x'] n0_y = params['n0_y'] n0_z = params['n0_z'] a0_x = params['a0_x'] a0_y = params['a0_y'] a0_z = params['a0_z'] # 原有模型的计算逻辑 y_pred = 你的原有模型计算代码 # 计算点积作为额外惩罚项 dot_val = n0_x*a0_x + n0_y*a0_y + n0_z*a0_z # 拼接残差,惩罚权重可根据你的数据量级调整,保证约束优先级 return np.append(data - y_pred, 100 * dot_val)
这种方法对求解器没有特殊要求,适配所有LMFIT的拟合场景。
方案2:使用求解器内置约束
如果你选用支持约束的后端求解器(比如trust-constr、SLSQP),可以直接传入等式约束参数:
# 定义等式约束,要求点积等于0 eq_constraint = [ { 'type': 'eq', 'fun': lambda p: p['n0_x']*p['a0_x'] + p['n0_y']*p['a0_y'] + p['n0_z']*p['a0_z'] } ] # 调用最小化时传入约束,需指定支持约束的求解器 fit_result = minimize(residual, param, args=(x, data), constraints=eq_constraint, method='trust-constr')
方案3:参数表达式直接约束(适合分量不为0的场景)
如果你能确定其中一个分量不会为0,可以直接把其中一个分量设置为派生参数,自动满足正交要求,比如确定n0_z不为0时:
# 直接把a0_z定义为派生参数,自动保证点积为0,不需要额外定义a0dotn0 param.add('a0_z', expr='-(n0_x*a0_x + n0_y*a0_y)/n0_z')
这种方法不需要修改残差函数,也不需要调整求解器,但是要注意避免出现除以0的情况。
内容的提问来源于stack exchange,提问作者Alan Bromborsky
相关产品推荐
相关产品推荐

