如何获取scipy least_squares迭代中间结果并绘图?
捕获SciPy least_squares迭代过程并可视化
scipy.optimize.least_squares本身没有直接输出迭代中间结果的选项,但可以通过自定义回调函数在每次迭代时记录参数、残差等数据,之后用Matplotlib完成可视化。以下是完整实现步骤:
1. 定义回调函数存储迭代轨迹
回调函数会在每轮迭代后触发,我们用它保存当前参数和残差平方和:
import numpy as np from scipy.optimize import least_squares import matplotlib.pyplot as plt # 初始化存储迭代数据的列表 iter_history = [] def track_iterations(xk): # 复制当前参数避免引用修改 current_params = xk.copy() # 计算当前残差平方和 residual = rosen_residual(current_params) residual_sum = np.sum(residual ** 2) # 存入历史记录 iter_history.append({ 'params': current_params, 'residual_sum': residual_sum })
2. 定义Rosenbrock函数的残差形式
least_squares以残差平方和最小化为目标,因此需要把Rosenbrock函数拆分为残差项:
def rosen_residual(x): # Rosenbrock函数的残差表示:对应原函数 (1-x0)² + 100*(x1-x0²)² return np.array([1 - x[0], 10 * (x[1] - x[0]**2)])
3. 执行优化并传入回调
指定方法为lm(Levenberg-Marquardt),同时传入回调函数:
# 初始猜测值 x0 = np.array([0, 0]) # 启动优化,开启迭代跟踪 result = least_squares( rosen_residual, x0, method='lm', callback=track_iterations )
4. 提取数据并可视化
从历史记录中提取参数轨迹和残差变化,绘制两种图:
# 提取迭代数据 params_history = np.array([entry['params'] for entry in iter_history]) residual_history = np.array([entry['residual_sum'] for entry in iter_history]) # 绘图1:参数(x0, x1)的迭代路径 plt.figure(figsize=(12, 5)) plt.subplot(1, 2, 1) plt.plot(params_history[:, 0], params_history[:, 1], 'o-', markersize=4, label='迭代轨迹') plt.scatter(result.x[0], result.x[1], c='red', s=100, label='最优解') plt.xlabel('x₀') plt.ylabel('x₁') plt.title('Rosenbrock函数迭代参数轨迹') plt.legend() # 绘图2:残差平方和随迭代次数的变化 plt.subplot(1, 2, 2) plt.plot(range(len(residual_history)), residual_history, 'b-') plt.xlabel('迭代次数') plt.ylabel('残差平方和') plt.title('残差平方和迭代下降曲线') plt.yscale('log') # 对数刻度更清晰展示快速下降过程 plt.tight_layout() plt.show()
关键细节
- 回调中必须用
.copy()复制参数数组,否则后续迭代会覆盖历史数据 - 你之前得到的108次迭代,
len(iter_history)会等于108,和优化结果的nit属性一致 - 如果需要跟踪更多细节(如LM的阻尼因子),可以通过查看优化结果的
optimality属性,或自定义残差函数时额外记录,但核心的参数轨迹用上述方法完全满足需求
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

