ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SciPy 优化器完全指南:从入门到实战

SciPy 优化器完全指南:从入门到实战 1. 引言在科学计算和工程实践中优化问题无处不在——从机器学习模型的超参数调优到工程设计中的成本最小化再到金融投资组合的最优配置。SciPy 作为 Python 科学计算生态的核心库其scipy.optimize模块提供了丰富且高效的优化算法工具箱涵盖了从无约束优化到约束优化、从线性规划到非线性最小二乘拟合的各类场景。本文将系统性地介绍 SciPy 优化器的核心概念和实战用法通过大量可运行的代码实例帮助读者快速掌握如何使用 SciPy 解决实际优化问题。2. 环境准备与基础概念在开始之前请确保已安装 SciPy 和相关的依赖库pip install scipy numpy matplotlib接下来我们导入本文所需的所有模块import numpy as np from scipy import optimize from scipy.optimize import minimize, Bounds, LinearConstraint, NonlinearConstraint import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D优化问题的基本形式为在给定约束条件下寻找使得目标函数f(x)取得最小值或最大值的自变量x。SciPy 中的优化器默认处理最小化问题如果需要最大化只需要对目标函数取负值即可。3. 无约束优化minimize 函数详解minimize是 scipy.optimize 中最核心的函数它统一了多种优化算法的接口。我们先从最简单的无约束优化开始。3.1 初识 minimize求解 Rosenbrock 函数Rosenbrock 函数是优化算法中经典的测试函数因其形似香蕉谷而得名其全局最小值位于 (1, 1) 处函数值为 0。# 定义 Rosenbrock 函数 def rosenbrock(x): return (1 - x[0])**2 100 * (x[1] - x[0]**2)**2 初始猜测值 x0 np.array([-1.2, 1.0]) 使用 BFGS 方法求解 result_bfgs minimize(rosenbrock, x0, methodBFGS) print(BFGS 优化结果) print(f最优解 x {result_bfgs.x}) print(f最小值 f(x) {result_bfgs.fun}) print(f迭代次数{result_bfgs.nit}) print(f是否收敛{result_bfgs.success}) print(f终止信息{result_bfgs.message})运行后你会看到优化器成功找到了位于[1.0, 1.0]的全局最小值。3.2 理解 OptimizeResult 对象minimize 函数返回一个OptimizeResult对象它包含丰富的优化过程信息。下面我们详细查看其字段def print_result_info(result, method_name): print(f\n{*50}) print(f方法{method_name}) print(f{*50}) print(f最优解 x {result.x}) print(f目标函数值{result.fun:.10f}) print(f梯度范数 {np.linalg.norm(result.jac)} if result.jac is not None else ) print(f迭代次数 {result.nit}) print(f函数求值次数{result.nfev}) print(f是否收敛 {result.success}) print(f终止信息 {result.message}) result minimize(rosenbrock, x0, methodBFGS) print_result_info(result, BFGS)OptimizeResult对象的关键属性包括x最优解向量fun最优解处的目标函数值jac最优解处的梯度向量nit迭代次数nfev目标函数求值次数success布尔值表示优化是否成功收敛3.3 梯度信息的重要性对于许多优化算法而言提供解析梯度可以显著提高收敛速度和精度。下面我们对比提供了梯度与不提供梯度的差异# Rosenbrock 函数的梯度 def rosenbrock_grad(x): grad np.zeros_like(x) grad[0] -2 * (1 - x[0]) - 400 * x[0] * (x[1] - x[0]**2) grad[1] 200 * (x[1] - x[0]**2) return grad x0 np.array([-1.2, 1.0]) 不提供梯度 result_no_grad minimize(rosenbrock, x0, methodBFGS) 提供梯度 result_with_grad minimize( rosenbrock, x0, methodBFGS, jacrosenbrock_grad ) print(对比结果) print(f无梯度 - 迭代次数: {result_no_grad.nit}, 函数求值次数: {result_no_grad.nfev}) print(f有梯度 - 迭代次数: {result_with_grad.nit}, 函数求值次数: {result_with_grad.nfev})通常提供解析梯度能减少函数求值次数加快收敛。4. 探索不同的优化算法SciPy 的minimize函数支持多种方法每种方法适用于不同的场景。我们使用一个二维测试函数来直观比较各算法的表现。4.1 定义测试函数并可视化# 一个具有多个局部最小值的测试函数Himmelblau 函数 def himmelblau(x): return (x[0]**2 x[1] - 11)**2 (x[0] x[1]**2 - 7)**2 可视化 def plot_surface(func, x_range(-5, 5), y_range(-5, 5), title目标函数曲面): x np.linspace(*x_range, 100) y np.linspace(*y_range, 100) X, Y np.meshgrid(x, y) Z func([X, Y]) fig plt.figure(figsize(12, 5)) ax1 fig.add_subplot(121, projection3d) ax1.plot_surface(X, Y, Z, cmapviridis, alpha0.8, edgecolornone) ax1.set_title(f{title} - 3D 视图) ax1.set_xlabel(x1) ax1.set_ylabel(x2) ax2 fig.add_subplot(122) contour ax2.contourf(X, Y, Z, levels50, cmapviridis) ax2.contour(X, Y, Z, levels50, colorswhite, alpha0.3, linewidths0.5) ax2.set_title(f{title} - 等高线图) ax2.set_xlabel(x1) ax2.set_ylabel(x2) plt.colorbar(contour, axax2, shrink0.8) plt.tight_layout() plt.show() plot_surface(himmelblau, titleHimmelblau 函数)4.2 梯度类方法BFGS 与 L-BFGS-B# 比较 BFGS 和 L-BFGS-B methods { BFGS: BFGS, L-BFGS-B: L-BFGS-B, CG: CG, } initial_guesses [ np.array([0.0, 0.0]), np.array([3.0, 3.0]), np.array([-4.0, -3.0]) ] print(不同方法在不同初始点的优化结果) for x0 in initial_guesses: print(f\n初始点 x0 {x0}) for name, method in methods.items(): result minimize(himmelblau, x0, methodmethod) print(f {name:10s}: x* [{result.x[0]:6.3f}, {result.x[1]:6.3f}], f* {result.fun:.6f}, 迭代: {result.nit})BFGS 是解决中等规模无约束问题的首选方法它通过近似 Hessian 矩阵来指导搜索方向通常收敛速度很快。L-BFGS-B 是其内存受限版本适合大规模问题且支持变量边界约束。4.3 无导数方法Nelder-Mead 与 Powell当目标函数不可导或梯度的计算代价过高时无导数方法就显得尤为重要。Nelder-Mead 单纯形法和 Powell 方法是两种经典选择# Nelder-Mead 方法 x0 np.array([0.0, 0.0]) result_nm minimize(himmelblau, x0, methodNelder-Mead, options{xatol: 1e-8, maxiter: 1000}) print(Nelder-Mead 方法结果) print_result_info(result_nm, Nelder-Mead) Powell 方法 result_powell minimize(himmelblau, x0, methodPowell, options{xtol: 1e-8, maxiter: 1000}) print_result_info(result_powell, Powell)Nelder-Mead 方法不需要梯度信息通过构建单纯形在 n 维空间中由 n1 个点构成的几何体并不断反射和收缩来逼近最小值。Powell 方法则通过沿共轭方向进行线搜索来优化目标函数在某些场景下可能比 Nelder-Mead 更快# 可视化优化路径可选扩展 def track_optimization(func, x0, method_name, boundsNone): points [x0.copy()] def callback(xk): points.append(xk.copy()) if bounds is not None: result minimize(func, x0, methodmethod_name, boundsbounds, callbackcallback) else: result minimize(func, x0, methodmethod_name, callbackcallback) return np.array(points), result 对比 Nelder-Mead 和 Powell 的搜索路径 x0 np.array([0.0, 0.0]) path_nm, res_nm track_optimization(himmelblau, x0, Nelder-Mead) path_powell, res_powell track_optimization(himmelblau, x0, Powell) 绘制搜索路径 x np.linspace(-5, 5, 200) y np.linspace(-5, 5, 200) X, Y np.meshgrid(x, y) Z himmelblau([X, Y]) plt.figure(figsize(10, 8)) plt.contourf(X, Y, Z, levels30, cmapviridis, alpha0.6) plt.contour(X, Y, Z, levels30, colorswhite, alpha0.2, linewidths0.5) plt.plot(path_nm[:, 0], path_nm[:, 1], r-o, markersize4, linewidth1.5, labelNelder-Mead 路径) plt.plot(path_powell[:, 0], path_powell[:, 1], b-s, markersize4, linewidth1.5, labelPowell 路径) plt.plot(x0[0], x0[1], ko, markersize8, label起点) plt.xlabel(x1, fontsize12) plt.ylabel(x2, fontsize12) plt.title(无导数方法优化路径对比, fontsize14) plt.legend(fontsize11) plt.grid(True, alpha0.3) plt.tight_layout() plt.show()4.4 算法选型指南下表总结了常用优化方法的适用场景方法需要梯度支持边界支持约束适用场景BFGS否自动近似否否中等规模无约束问题L-BFGS-B否自动近似是否大规模问题有边界约束CG是否否大规模无约束问题Nelder-Mead否否否不可导函数低维问题Powell否否否不可导函数线搜索效率高SLSQP否自动近似是是带约束的通用问题COBYLA否是是带约束无梯度场景trust-constr否自动近似是是大规模约束优化5. 约束优化实战实际工程中的优化问题几乎都带有各种约束。SciPy 提供了多种方式来处理约束包括简单的变量边界和复杂的等式与不等式约束。5.1 边界约束Bounds 对象最简单的约束是限制变量的取值范围。我们通过一个经典的最优投资组合问题来演示# 示例最小化函数 f(x) (x[0]-2)**2 (x[1]-3)**2约束 0 x[0] 5, 1 x[1] 4 def objective_with_bounds(x): return (x[0] - 2)**2 (x[1] - 3)**2 x0_bound np.array([0.0, 0.0]) 定义边界 bounds Bounds([0.0, 1.0], [5.0, 4.0]) 使用 L-BFGS-B天然支持边界 result_bound minimize(objective_with_bounds, x0_bound, methodL-BFGS-B, boundsbounds) print(带边界约束的优化结果) print_result_info(result_bound, L-BFGS-B with Bounds)5.2 线性约束与非线性约束SciPy 支持通过LinearConstraint和NonlinearConstraint对象定义复杂的约束条件。下面的例子演示了如何在一个二维优化问题中同时应用两种约束# 目标函数最小化 (x[0]-1)**2 (x[1]-2.5)**2 def objective_constrained(x): return (x[0] - 1)**2 (x[1] - 2.5)**2 约束条件 1. 线性不等式约束x[0] 2x[1] 4 → -x[0] - 2x[1] 4 0 linear_constraint LinearConstraint( np.array([[1, 2]]), # 系数矩阵 A lbnp.array([4]), # 下界 Ax 4等价于 lb ubnp.array([np.inf]) # 上界 Ax inf ) 2. 非线性约束x[0]**2 x[1]**2 20 def con_fun(x): return x[0]**2 x[1]**2 nonlinear_constraint NonlinearConstraint( con_fun, lb-np.inf, # 下界 ub20.0 # 上界 ) 使用 SLSQP 求解 x0_constrained np.array([2.0, 0.0]) result_constrained minimize( objective_constrained, x0_constrained, methodSLSQP, constraints[linear_constraint, nonlinear_constraint], options{maxiter: 500, ftol: 1e-9} ) print(带线性与非线性约束的优化结果) print_result_info(result_constrained, SLSQP with Constraints) print(f验证线性约束 x12x2 {result_constrained.x[0] 2result_constrained.x[1]:.3f} (应 4)) print(f验证非线性约束 x1²x2² {result_constrained.x[0]**2 result_constrained.x[1]**2:.3f} (应 20))5.3 实际案例投资组合优化投资组合优化是约束优化最经典的应用场景之一。目标是在给定预期收益的条件下最小化风险方差同时满足权重之和为 1全部投入和各资产权重在合理范围内的约束# 模拟三个资产的历史收益率 np.random.seed(42) n_assets 3 n_days 252 daily_returns np.random.randn(n_days, n_assets) * 0.01 计算协方差矩阵 cov_matrix np.cov(daily_returns.T) 目标函数组合方差风险 def portfolio_variance(weights): return weights cov_matrix weights 约束1权重之和为 1 weights_sum_constraint LinearConstraint( np.ones(n_assets), lb1.0, ub1.0 ) 约束2组合预期收益至少为某个目标 target_return 0.001 mean_returns np.mean(daily_returns, axis0) return_constraint LinearConstraint( mean_returns, lbtarget_return, ubnp.inf ) 边界每项资产权重在 0% 到 60% 之间 weight_bounds Bounds([0.0]*n_assets, [0.6]*n_assets) 初始权重等权重 x0_portfolio np.array([1/n_assets] * n_assets) 求解 result_portfolio minimize( portfolio_variance, x0_portfolio, methodSLSQP, boundsweight_bounds, constraints[weights_sum_constraint, return_constraint], options{maxiter: 1000, ftol: 1e-12} ) print(投资组合优化结果) print(f最优权重{result_portfolio.x}) print(f组合波动率标准差{np.sqrt(result_portfolio.fun)*100:.2f}%) print(f预期日收益率{result_portfolio.x mean_returns * 100:.3f}%) print(f权重之和{np.sum(result_portfolio.x):.6f})6. 最小二乘与曲线拟合数据拟合是科学实验和工程测量中最常见的任务之一。SciPy 提供了least_squares和curve_fit两个强大工具来处理线性和非线性最小二乘问题。6.1 curve_fit非线性曲线拟合curve_fit是对 Levenberg-Marquardt 算法的友好封装可以直接通过「模型函数 数据」的方式拟合参数from scipy.optimize import curve_fit 生成带噪声的示例数据阻尼振荡模型 def damped_oscillation(t, A, omega, zeta, phi): return A * np.exp(-zeta * t) * np.cos(omega * t phi) np.random.seed(123) t_data np.linspace(0, 10, 100) true_params [3.0, 2.0, 0.3, 0.5] y_true damped_oscillation(t_data, *true_params) y_noisy y_true 0.3 * np.random.normal(sizet_data.shape) 使用 curve_fit 拟合 initial_guess [2.0, 1.5, 0.2, 0.0] # 初始猜测 popt, pcov curve_fit(damped_oscillation, t_data, y_noisy, p0initial_guess) perr np.sqrt(np.diag(pcov)) # 参数的标准误差 print(curve_fit 拟合结果) print(f{参数:8s} {真实值:8s} {拟合值:8s} {标准误差:8s}) for i, (true, fit, err) in enumerate(zip(true_params, popt, perr)): print(f{A,ω,ζ,φ[i]:8s} {true:8.3f} {fit:8.3f} {err:8.4f}) 可视化结果 plt.figure(figsize(10, 5)) plt.scatter(t_data, y_noisy, s15, alpha0.6, label带噪声的观测数据) plt.plot(t_data, y_true, g-, linewidth2, label真实曲线) plt.plot(t_data, damped_oscillation(t_data, *popt), r--, linewidth2, label拟合曲线) plt.xlabel(时间 t, fontsize12) plt.ylabel(振幅, fontsize12) plt.title(阻尼振荡曲线拟合, fontsize14) plt.legend(fontsize11) plt.grid(True, alpha0.3) plt.tight_layout() plt.show()6.2 least_squares灵活的最小二乘工具least_squares提供了比curve_fit更底层的控制能力。它直接优化残差向量的平方和适合处理带边界约束的拟合问题from scipy.optimize import least_squares 使用 least_squares 拟合同一个模型 def residuals(params, t, y): return damped_oscillation(t, *params) - y 带边界约束参数值必须为正 result_ls least_squares( residuals, initial_guess, bounds([0.0, 0.0, 0.0, -np.inf], [10.0, 10.0, 5.0, np.inf]), args(t_data, y_noisy), methodtrf, # Trust Region Reflective verbose0 ) print(\nleast_squares 拟合结果) print(f拟合参数{result_ls.x}) print(f残差范数{result_ls.cost:.6f}) print(f是否成功{result_ls.success}) print(f迭代次数{result_ls.nfev})7. 全局优化跳出局部极小值当目标函数存在多个局部极小值时梯度类方法可能会陷入局部最优。SciPy 提供了多种全局优化算法来应对这种情况。7.1 微分进化算法微分进化Differential Evolution是一种基于种群的随机搜索算法不需要梯度信息能够有效地探索整个搜索空间from scipy.optimize import differential_evolution 使用多峰函数来展示全局优化的必要性 def multimodal_func(x): return np.sin(x[0]) * np.cos(x[1]) 0.01 * (x[0]**2 x[1]**2) 可视化多峰函数 x_grid np.linspace(-5, 5, 200) y_grid np.linspace(-5, 5, 200) X_grid, Y_grid np.meshgrid(x_grid, y_grid) Z_grid multimodal_func([X_grid, Y_grid]) plt.figure(figsize(10, 8)) plt.contourf(X_grid, Y_grid, Z_grid, levels30, cmapviridis, alpha0.8) 局部优化容易陷入局部极小 for start_point in [[-3.0, -3.0], [4.0, 3.0], [-4.0, 4.0]]: result_local minimize(multimodal_func, start_point, methodBFGS) plt.plot(result_local.x[0], result_local.x[1], rx, markersize10, markeredgewidth2) 全局优化 bounds_de [(-5, 5), (-5, 5)] result_global differential_evolution(multimodal_func, bounds_de, seed42) plt.plot(result_global.x[0], result_global.x[1], y*, markersize15, markeredgewidth2, labelf微分进化全局最优: f{result_global.fun:.3f}) plt.xlabel(x1, fontsize12) plt.ylabel(x2, fontsize12) plt.title(全局优化 vs. 局部优化红叉为局部极小点, fontsize14) plt.legend(fontsize11) plt.grid(True, alpha0.3) plt.tight_layout() plt.show() print(\n微分进化全局优化结果) print(f全局最优解{result_global.x}) print(f全局最小值{result_global.fun:.6f}) print(f收敛迭代数{result_global.nit})7.2 shgo单纯形同调全局优化shgoSimplicial Homology Global Optimization是一种基于拓扑学思想的全局优化方法它能同时返回局部最优点和全局最优点from scipy.optimize import shgo result_shgo shgo(multimodal_func, bounds_de, n100, iters5, sampling_methodsobol) print(shgo 全局优化结果) print(f全局最优解{result_shgo.x}) print(f全局最小值{result_shgo.fun:.6f}) print(f找到的局部极值点数量{len(result_shgo.xl)})7.3 basinhopping盆地跳跃算法basinhopping 算法结合了局部优化和随机扰动通过模拟「跳跃」来探索不同盆地from scipy.optimize import basinhopping x0_bh np.array([0.0, 0.0]) result_bh basinhopping( multimodal_func, x0_bh, niter100, stepsize0.5, minimizer_kwargs{method: BFGS} ) print(basinhopping 全局优化结果) print(f全局最优解{result_bh.x}) print(f全局最小值{result_bh.fun:.6f})8. 线性规划linprog 实战线性规划在资源分配、物流运输和生产优化等领域有着广泛的应用。SciPy 的linprog函数提供了对多种线性规划求解器的统一接口。from scipy.optimize import linprog 示例最小化 c·x满足 A_ub·x b_ub, A_eq·x b_eq, bounds 目标minimize -x1 - 2*x2 约束2*x1 x2 20 -4x1 5x2 10 x1 - 2*x2 2 x1 x2 8 x1 0, x2 0 c [-1, -2] # 目标函数系数注意负号表示最大化 A_ub [[2, 1], [-4, 5], [1, -2]] # 不等式约束系数矩阵 b_ub [20, 10, 2] # 不等式约束右端项 A_eq [[1, 1]] # 等式约束系数矩阵 b_eq [8] # 等式约束右端项 bounds [(0, None), (0, None)] # 变量边界x 0 result_lp linprog(c, A_ubA_ub, b_ubb_ub, A_eqA_eq, b_eqb_eq, boundsbounds, methodhighs) print(线性规划求解结果) print(f最优解x1 {result_lp.x[0]:.2f}, x2 {result_lp.x[1]:.2f}) print(f最优值{-result_lp.fun:.2f}最大化目标) print(f是否成功{result_lp.success}) print(f求解器{result_lp.message}) 验证约束 print(f\n验证约束) print(f2x1 x2 {2result_lp.x[0] result_lp.x[1]:.2f} (应 20)) print(f-4x1 5x2 {-4result_lp.x[0] 5result_lp.x[1]:.2f} (应 10)) print(fx1 - 2x2 {result_lp.x[0] - 2result_lp.x[1]:.2f} (应 2)) print(fx1 x2 {result_lp.x[0] result_lp.x[1]:.2f} (应 8))9. 根求解与方程求解SciPy 的 optimize 模块还包含了功能强大的求根工具可以求解标量方程和方程组的根。9.1 标量求根root_scalarfrom scipy.optimize import root_scalar 求解方程 cos(x) x def f_scalar(x): return np.cos(x) - x 使用 Brent 方法默认稳健且高效 result_brent root_scalar(f_scalar, bracket[0, 1], methodbrentq) print(标量求根结果) print(f方程 cos(x) x 的根: x {result_brent.root:.10f}) print(f验证: cos(x) - x {f_scalar(result_brent.root):.2e}) print(f迭代次数{result_brent.iterations}) 使用割线法Secant result_secant root_scalar(f_scalar, x00.5, x10.8, methodsecant) print(f\n割线法结果: x {result_secant.root:.10f})9.2 方程组求根root 函数from scipy.optimize import root 求解方程组 x^2 y^2 25 x*y 12 def system(vars): x, y vars return [x2 y2 - 25, x*y - 12] 初始猜测使用两组不同初始值以获得不同解 sol1 root(system, [3, 4]) sol2 root(system, [-3, -4]) print(方程组求根结果) print(f解1: x {sol1.x[0]:.6f}, y {sol1.x[1]:.6f}, 残差: {np.linalg.norm(system(sol1.x)):.2e}) print(f解2: x {sol2.x[0]:.6f}, y {sol2.x[1]:.6f}, 残差: {np.linalg.norm(system(sol2.x)):.2e})10. 实战案例机器学习中的超参数优化优化技术在机器学习中扮演着核心角色。下面我们构造一个完整的案例展示如何利用 SciPy 优化器来调优 Ridge 回归的正则化参数from sklearn.datasets import make_regression from sklearn.linear_model import Ridge from sklearn.model_selection import cross_val_score from sklearn.preprocessing import StandardScaler 生成模拟数据 np.random.seed(42) X, y make_regression(n_samples200, n_features10, noise20, random_state42) scaler StandardScaler() X_scaled scaler.fit_transform(X) 定义目标函数负的交叉验证 R² 分数最小化负值 最大化 R² def objective_alpha(log_alpha): alpha np.exp(log_alpha[0]) # 将 log(alpha) 转换为 alpha model Ridge(alphaalpha) scores cross_val_score(model, X_scaled, y, cv5, scoringr2) return -np.mean(scores) # 返回负 R² 用于最小化 使用 Nelder-Mead 搜索最优 alpha x0_log_alpha np.array([0.0]) # 初始 log(alpha) 0 → alpha 1 result_alpha_opt minimize( objective_alpha, x0_log_alpha, methodNelder-Mead, options{xatol: 1e-6, maxiter: 200} ) optimal_alpha np.exp(result_alpha_opt.x[0]) print(Ridge 正则化参数优化结果) print(f最优 log(alpha) {result_alpha_opt.x[0]:.4f}) print(f最优 alpha {optimal_alpha:.6f}) print(f最佳交叉验证 R² {-result_alpha_opt.fun:.4f}) 可视化 alpha 与 R² 的关系 alphas np.logspace(-3, 3, 50) cv_scores [] for alpha in alphas: model Ridge(alphaalpha) scores cross_val_score(model, X_scaled, y, cv5, scoringr2) cv_scores.append(np.mean(scores)) plt.figure(figsize(10, 5)) plt.semilogx(alphas, cv_scores, b-o, markersize3, linewidth1.5) plt.axvline(optimal_alpha, colorr, linestyle--, linewidth2, labelf最优 alpha {optimal_alpha:.4f}) plt.xlabel(alpha对数刻度, fontsize12) plt.ylabel(交叉验证 R² 分数, fontsize12) plt.title(Ridge 回归正则化参数调优, fontsize14) plt.legend(fontsize11) plt.grid(True, alpha0.3) plt.tight_layout() plt.show()11. 总结与最佳实践通过本文的学习我们系统地掌握了 SciPy 优化器的核心知识和实战技巧。最后我们总结几条重要的最佳实践建议优先理解问题性质在选择优化算法之前先判断目标函数是否可导、是否存在多个局部极小值、是否带有约束条件。了解问题的特性是选择合适算法的前提。从简单到复杂对于中小规模的无约束问题BFGS 通常是稳健的默认选择当问题涉及边界或约束时再逐步引入 L-BFGS-B、SLSQP 或 trust-constr。善用梯度信息如果能够提供解析梯度应优先提供给优化器。这不仅能加速收敛还能提高数值稳定性。当梯度难以计算时再退回到无导数方法。注意初值敏感性梯度类方法的结果可能依赖于初始猜测值。建议从多个不同的初始点出发进行优化以增加找到全局最优解的概率。当问题明显存在多个局部极小值时优先使用differential_evolution或basinhopping等全局优化方法。验证约束满足情况求解约束优化问题后务必检查最优解是否满足所有约束条件尤其是接近边界的约束避免因数值误差导致结果无效。结合交叉验证评估在模型超参数调优中优化目标通常建立在交叉验证指标之上。注意设置合理的容差和最大迭代次数避免过拟合评估指标。查阅官方文档SciPy 的优化模块功能非常丰富本文仅覆盖了最常用的部分。建议在遇到特殊需求时查阅 SciPy 官方文档探索更多高级选项。
返回列表