You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在scipy.optimize.nnls中固定部分系数求解剩余非负最小二乘解?

如何在scipy.optimize.nnls中固定部分系数值?

好问题!scipy.optimize.nnls本身并没有直接提供固定部分系数的参数,但我们可以通过重构优化问题的方式轻松实现这个需求。核心思路是把固定系数的影响从目标方程中提前剔除,然后对剩余的自由变量求解非负最小二乘。

具体原理

原问题是求解:

min ||A @ x - b||²,约束 x ≥ 0

如果我们要固定x[i] = fixed_val(fixed_val ≥ 0,符合非负约束),可以把这一项从方程中分离出来:

  1. 计算固定项对目标向量的贡献:A[:, i] * fixed_val
  2. 用原目标向量减去这个贡献,得到新的目标向量:b_new = b - A[:, i] * fixed_val
  3. 从矩阵A中删除第i列,得到新的矩阵A_new
  4. 对A_new和b_new运行nnls,得到剩余自由变量的解x_rest
  5. 把固定值插回x_rest的对应位置,得到最终的完整解x

基于你的代码修改的示例

假设你要固定第一个系数为0.9,可以这样修改代码:

#! /usr/bin/env python3
import numpy as np
import scipy.optimize as soptimize

if __name__ == '__main__':
    C = np.array([[112.771820, 174.429720, 312.175750, 97.348620],
                  [112.857010, 174.208300, 312.185270, 93.467580],
                  [114.897210, 175.661850, 314.275100, 99.015480] ]);
    d = np.array([[112.7718, 174.4297, 312.1758, 97.3486]]);
    
    # 配置固定参数:索引0对应的值为0.9
    fixed_idx = 0
    fixed_val = 0.9

    for line in d:
        # 1. 重构矩阵:移除固定系数对应的列
        A_new = np.delete(C.T, fixed_idx, axis=1)
        # 2. 重构目标向量:减去固定项的贡献
        b_new = line - C.T[:, fixed_idx] * fixed_val
        
        # 3. 求解剩余变量的非负最小二乘
        ret_rest, _ = soptimize.nnls(A_new, b_new)
        
        # 4. 插入固定值,得到完整解
        ret = np.insert(ret_rest, fixed_idx, fixed_val)
        
        print("带固定值的解:", ret)
        # 可选:验证拟合误差
        print("拟合误差平方:", np.linalg.norm(C.T @ ret - line)**2)

扩展:固定多个系数的情况

如果需要固定多个系数,只需要批量处理即可。比如固定索引0和1的值为0.9和0.06:

# 配置多个固定参数
fixed_indices = [0, 1]
fixed_vals = [0.9, 0.06]

for line in d:
    # 计算所有固定项的总贡献
    total_fixed_contrib = sum(C.T[:, idx] * val for idx, val in zip(fixed_indices, fixed_vals))
    b_new = line - total_fixed_contrib
    
    # 删除所有固定列
    A_new = np.delete(C.T, fixed_indices, axis=1)
    
    # 求解剩余变量
    ret_rest, _ = soptimize.nnls(A_new, b_new)
    
    # 组装完整解
    ret = np.zeros(C.T.shape[1])
    ret[fixed_indices] = fixed_vals
    # 填充剩余自由变量的解
    free_indices = np.setdiff1d(range(C.T.shape[1]), fixed_indices)
    ret[free_indices] = ret_rest
    
    print("多固定值的解:", ret)

注意事项

  • 固定值必须非负,否则违反nnls的非负约束,结果没有实际意义。
  • 如果重构后的b_new出现负数,nnls仍然会求解,但建议检查最终解的拟合效果是否符合预期。
  • 这种方法完全基于原生的nnls函数,不需要引入额外的优化库,效率和原函数一致。

内容的提问来源于stack exchange,提问作者elody wenge

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:04:52