如何调整SciPy minimizer参数 加速数千变量最小二乘成本函数优化
优化方案
一、调整scipy.optimize.minimize的核心参数提升效率
- 更换适配高维问题的求解方法
默认调用的BFGS方法需要存储完整的近似海森矩阵,在数千维度的场景下计算和存储开销极高。指定method='L-BFGS-B',采用有限内存BFGS算法,仅保留最近几步的迭代信息计算下降方向,内存和计算开销能降低一个数量级。 - 传入解析梯度避免数值差分开销
默认情况下求解器会通过数值差分计算梯度,N维变量每轮迭代需要调用N次成本函数,你这7500维的场景下这部分开销占比极高。自行实现解析梯度通过jac参数传入,能大幅降低迭代耗时。
你场景下的梯度计算实现如下:
def gradFunction(weights): weights = np.reshape(weights, newshape=(100, 75)) residual = np.sum(x * weights, axis=1) - y # 广播后逐元素相乘,得到梯度后拉平 grad = 2 * (x * residual[:, np.newaxis]) return grad.flatten()
调用minimize时加上jac=gradFunction即可。
- 放宽迭代终止阈值
默认的收敛阈值gtol=1e-8、ftol=2.2e-9精度过高,如果你业务不需要极高精度,适当调大阈值:比如设置options={'gtol':1e-4, 'ftol':1e-5},能减少大量不必要的迭代步数。 - 限制最大迭代次数
通过options={'maxiter': 1000}设置合理的迭代上限,避免求解器在收敛边缘反复迭代浪费时间。
调整后的minimize调用示例:
result = minimize( costFunction, startingWeights.flatten(), method='L-BFGS-B', jac=gradFunction, options={'gtol': 1e-4, 'ftol':1e-5, 'maxiter': 1000} )
二、更适配最小二乘场景的高效替代方案
你当前的成本函数是典型的线性最小二乘问题,完全没必要用通用的非线性优化器,有更高效的方案:
- 无约束场景直接用闭式解
线性最小二乘存在解析最优解,直接调用numpy.linalg.lstsq即可,耗时仅需毫秒级,远快于任何迭代优化方案:
# 把问题转化为标准线性最小二乘形式Xβ = y X = x.reshape(100, -1) opt_weights, _, _, _ = np.linalg.lstsq(X, y, rcond=None) opt_weights = opt_weights.reshape(100,75)
- 如果后续要加约束/改成非线性最小二乘,用
scipy.optimize.least_squares
这个求解器是专门为最小二乘问题设计的,会利用残差的结构优化计算,效率比通用minimize高3~10倍,直接传入残差计算函数即可,不用自己算损失求和:
def residualFunction(weights): weights = np.reshape(weights, newshape=(100,75)) weighted = np.sum(x * weights, axis=1) return y - weighted result = least_squares(residualFunction, startingWeights.flatten(), method='trf')
内容的提问来源于stack exchange,提问作者John Sorensen
相关产品推荐
相关产品推荐

