如何为SciPy的LSQR/LSMR求解添加变量边界约束?
解决带变量边界约束的超定方程组最小二乘问题
SciPy的LSQR和LSMR都是无约束线性最小二乘求解器,设计时未支持变量边界约束,因此无法直接通过这两个函数实现你需要的x(1)>=0约束。以下是两种可行的替代方案:
方案1:使用scipy.optimize.lsq_linear(推荐)
这是SciPy专门为带边界约束的线性最小二乘问题设计的求解器,直接通过bounds参数设置变量约束即可,效率和精度都优于通用优化器。
代码示例
假设你的矩阵A是469×3维度,向量b是469维:
import numpy as np from scipy.optimize import lsq_linear # 替换为你的实际数据 # A = ... # b = ... # 设置边界:x[0](对应你输出中的x(1))>=0,其余变量无约束 bounds = ([0, -np.inf, -np.inf], [np.inf, np.inf, np.inf]) # 求解带约束的最小二乘问题 result = lsq_linear(A, b, bounds=bounds) # 输出结果 print("带约束的最小二乘解:") print(result.x) print("残差平方和的一半:", result.cost) print("求解状态:", result.status)
该方法会自动找到满足x(1)>=0的最优解,对应你期望的迭代终止在x(1)=0.27附近的状态。
方案2:使用scipy.optimize.minimize结合约束优化器
将最小二乘问题转化为无约束优化目标(最小化||Ax - b||²),再使用支持边界约束的优化器(如L-BFGS-B)求解。
代码示例
import numpy as np from scipy.optimize import minimize # 定义最小二乘目标函数 def ls_objective(x, A, b): return np.linalg.norm(A @ x - b) ** 2 # 替换为你的实际数据 # A = ... # b = ... # 初始猜测值(可使用LSQR的无约束解或全0向量) x0 = np.zeros(3) # 设置边界:x[0] >=0,其余变量无约束 bounds = [(0, None), (None, None), (None, None)] # 调用带约束的优化器求解 result = minimize(ls_objective, x0, args=(A, b), bounds=bounds, method='L-BFGS-B') # 输出结果 print("带约束的解:") print(result.x) print("目标函数值(残差平方和):", result.fun)
关键说明
lsq_linear是专门针对线性带约束最小二乘的优化实现,在问题规模较大时,比通用优化器minimize更高效。- 若你坚持使用类似LSQR的迭代方法,目前SciPy生态中没有直接扩展LSQR支持约束的工具,上述两种方案是最直接的替代路径。
内容的提问来源于stack exchange,提问作者samman
相关产品推荐
相关产品推荐

