scikit-opt 模拟退火(SA)深入:Fast / Boltzmann / Cauchy 三种降温策略的原理、参数与实战
【免费下载链接】scikit-optGenetic Algorithm, Particle Swarm Optimization, Simulated Annealing, Ant Colony Optimization Algorithm,Immune Algorithm, Artificial Fish Swarm Algorithm, Differential Evolution and TSP(Traveling salesman)项目地址: https://gitcode.com/GitHub_Trending/sci/scikit-opt
本篇文章以 scikit-opt 仓库中的 docs/en/more_sa.md 为主体,系统讲解模拟退火(Simulated Annealing,SA)在 scikit-opt 中的三种具体实现:快速模拟退火(Fast)、玻尔兹曼模拟退火(Boltzmann)与柯西模拟退火(Cauchy)。你将学会三种策略各自的状态更新公式与降温曲线,掌握SAFast、SABoltzmann、SACauchy的完整调用方式(含边界约束版本),并结合 sko/SA.py 的源码理解 Metropolis 准则、链长与停止条件等底层机制,最终能在 examples/demo_sa.py 的基础上快速完成自己的优化任务。
一、模拟退火三策略的数学模型:三种"降温 + 抽样"方案
scikit-opt 的模拟退火实现把"生成新解"(抽样)与"温度更新"(降温)两件事绑定在一起,形成三种风格迥异的策略。文档 docs/en/more_sa.md 给出了三种策略的数学定义,它们分别对应源码中SAFast、SACauchy、SABoltzmann三个类(sko/SA.py)。
1.1 Fast(快速退火)策略
u ~ Uniform(0, 1, size = d) y = sgn(u - 0.5) * T * ((1 + 1/T)**abs(2*u - 1) - 1.0) xc = y * (upper - lower) x_new = x_old + xc c = n * exp(-n * quench) T_new = T0 * exp(-c * k**quench)该策略基于"快速退火"(Fast Simulated Annealing)思想:扰动幅度由温度T与均匀分布随机数u共同决定,扰动呈近似柯西分布的重尾特性,有利于在大范围内跳变;降温速度呈指数级衰减,收敛速度较快。对照源码,SAFast.get_new_x将公式中的upper - lower实现为可配置的hop步长(sko/SA.py),cool_down则按T_new = T_max * exp(-c * k**quench)降温(sko/SA.py),其中c = m * exp(-n * quench)(sko/SA.py)。
1.2 Cauchy(柯西)策略
u ~ Uniform(-pi/2, pi/2, size=d) xc = learn_rate * T * tan(u) x_new = x_old + xc T_new = T0 / (1 + k)柯西策略的扰动服从柯西分布(通过tan(u)生成),同样具有重尾特性,允许偶尔产生大步长跳跃;温度随迭代次数k线性反比下降(T0 / (1 + k))。源码实现中,扰动幅度为learn_rate * T * tan(u),其中learn_rate默认取0.5(sko/SA.py),降温逻辑见 sko/SA.py。
1.3 Boltzmann(玻尔兹曼)策略
std = minimum(sqrt(T) * ones(d), (upper - lower) / (3*learn_rate)) y ~ Normal(0, std, size = d) x_new = x_old + learn_rate * y T_new = T0 / log(1 + k)玻尔兹曼策略的扰动服从高斯分布:标准差取sqrt(T)与边界约束折算值两者中的较小者,使扰动范围受边界约束钳制;温度按对数函数T0 / log(1 + k)缓慢下降,属于三类中降温最慢、搜索最细致的方案。源码中std = min(sqrt(T), hop / (3 * learn_rate))的钳制逻辑在 sko/SA.py 实现,降温逻辑见 sko/SA.py。
三种策略核心差异可总结如下:
| 策略 | 生成新解 | 降温公式 | 特点 |
|---|---|---|---|
| Fast | 重尾扰动,xc = y * hop | T_new = T0 * exp(-c * k**quench) | 降温快,适合快速粗寻优 |
| Cauchy | 柯西分布扰动,xc = learn_rate * T * tan(u) | T_new = T0 / (1 + k) | 允许大步长跳跃 |
| Boltzmann | 高斯扰动,标准差受边界钳制 | T_new = T0 / log(1 + k) | 降温最慢,搜索细致 |
二、三种策略的统一骨架:SimulatedAnnealingBase 与 Metropolis 准则
无论选择哪种策略,它们都继承自SimulatedAnnealingBase(sko/SA.py),共享同一套核心流程:
- 初始化:以
x0作为初始解,计算初始函数值作为best_y,温度初始化为T_max(sko/SA.py); - 内层循环(链):在每一温度下迭代
L次,通过get_new_x生成新解,并依据Metropolis 准则决定是否接受:
# Metropolis df = y_new - y_current if df < 0 or np.exp(-df / self.T) > np.random.rand(): x_current, y_current = x_new, y_new if y_new < self.best_y: self.best_x, self.best_y = x_new, y_new(见 sko/SA.py)其含义是:新解更优(df < 0)必然接受;新解更差时,以概率exp(-df / T)接受,温度越高越容易"容忍"坏解,从而跳出局部最优;
- 外层循环:每完成一轮链,调用
cool_down()降温,并记录generation_best_Y、generation_best_X历史(sko/SA.py); - 停止条件:温度降至
T_min以下,或连续max_stay_counter轮最优值未改善(sko/SA.py)。
需要注意的是,run()返回(best_x, best_y),同时结果也保存在对象的best_x、best_y、best_x_history、best_y_history属性中,便于后续绘图分析(examples/demo_sa.py)。基类还提供了fit = run的兼容别名(sko/base.py),不过官方更推荐使用run()。
三、Fast 模拟退火:基础用法与边界约束
3.1 基础用法
SAFast的类名定义为SA = SAFast(sko/SA.py),因此from sko.SA import SA拿到的就是 Fast 策略。文档及示例代码 examples/demo_sa.py 中的基础用法如下:
from sko.SA import SAFast demo_func = lambda x: x[0] ** 2 + (x[1] - 0.05) ** 2 + x[2] ** 2 sa_fast = SAFast(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150) sa_fast.run() print('Fast Simulated Annealing: best_x is ', sa_fast.best_x, 'best_y is ', sa_fast.best_y)其中demo_func是一个三维连续函数,理论最优点接近(0, 0.05, 0)。运行后best_x会收敛到该点附近,best_y接近 0。
3.2 带边界约束的用法
当决策变量存在取值范围时,可传入lb(下界)与ub(上界),两者必须同时给出,否则抛错(sko/SA.py)。边界约束版本会在每次生成新解后用np.clip将解限制在界内(sko/SA.py):
from sko.SA import SAFast sa_fast = SAFast(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150, lb=[-1, 1, -1], ub=[2, 3, 4]) sa_fast.run() print('Fast Simulated Annealing with bounds: best_x is ', sa_fast.best_x, 'best_y is ', sa_fast.best_y)源码提示:从 sko/SA.py 的实现看,
SAFast实际从kwargs中读取的调温参数是m(默认 1)、n(默认 1)、quench(默认 1),以及影响扰动范围的hop(有边界时默认ub - lb,无边界时默认 10,见 sko/SA.py)。文档示例中传入的q=0.99会被**kwargs静默吸收而不生效,若要调节降温速度,应改用quench等参数。
四、Boltzmann 模拟退火:基础用法与边界约束
SABoltzmann使用高斯扰动与对数降温(sko/SA.py)。文档示例(对应 examples/demo_sa.py):
from sko.SA import SABoltzmann sa_boltzmann = SABoltzmann(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150) sa_boltzmann.run() print('Boltzmann Simulated Annealing: best_x is ', sa_boltzmann.best_x, 'best_y is ', sa_boltzmann.best_y)带边界约束版本(examples/demo_sa.py),注意示例中lb传的是标量-1,ub传的是列表[2, 3, 4],源码会用np.ones(n_dim)自动广播成与维度匹配的数组(sko/SA.py):
from sko.SA import SABoltzmann sa_boltzmann = SABoltzmann(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150, lb=-1, ub=[2, 3, 4]) sa_boltzmann.run() print('Boltzmann Simulated Annealing with bounds: best_x is ', sa_boltzmann.best_x, 'best_y is ', sa_boltzmann.best_y)SABoltzmann还接受learn_rate参数(默认 0.5),它同时参与扰动标准差钳制与解更新的缩放(sko/SA.py),可视为该策略的核心灵敏度旋钮。
五、Cauchy 模拟退火:基础用法与边界约束
SACauchy使用柯西分布扰动与线性反比降温(sko/SA.py)。文档示例(对应 examples/demo_sa.py):
from sko.SA import SACauchy sa_cauchy = SACauchy(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150) sa_cauchy.run() print('Cauchy Simulated Annealing: best_x is ', sa_cauchy.best_x, 'best_y is ', sa_cauchy.best_y)带边界约束版本(examples/demo_sa.py):
from sko.SA import SACauchy sa_cauchy = SACauchy(func=demo_func, x0=[1, 1, 1], T_max=1, T_min=1e-9, q=0.99, L=300, max_stay_counter=150, lb=[-1, 1, -1], ub=[2, 3, 4]) sa_cauchy.run() print('Cauchy Simulated Annealing with bounds: best_x is ', sa_cauchy.best_x, 'best_y is ', sa_cauchy.best_y)同样地,SACauchy的有效调节参数是learn_rate(默认 0.5)与hop,q不参与计算。
六、参数一览表:如何为三种策略调参
综合 docs/en/more_sa.md 与 sko/SA.py 源码,三类模拟退火共享以下构造参数:
| 参数 | 默认值 | 作用 |
|---|---|---|
func | 必填 | 目标函数,输入一维数组,输出标量 |
x0 | 必填 | 初始解,一维数组,其长度决定n_dim |
T_max | 100 | 初始温度,须满足T_max > T_min > 0(sko/SA.py) |
T_min | 1e-7 | 终止温度 |
L | 300 | 每个温度下的迭代次数(链长,Long of Chain,sko/SA.py) |
max_stay_counter | 150 | 最优值连续未改善的轮数上限,用于提前停止(冷却计数,sko/SA.py) |
lb/ub | 无 | 决策变量上下界,需同时传入,可传标量或数组;不传则无边界 |
hop | 有界时ub-lb,无界时 10 | Fast 策略的扰动缩放步长,也参与 Boltzmann 的标准差钳制 |
策略专属参数:
| 策略 | 专属参数 | 默认值 | 作用 |
|---|---|---|---|
SAFast | m、n、quench | 1、1、1 | 控制指数降温速度,c = m * exp(-n * quench) |
SABoltzmann | learn_rate | 0.5 | 扰动标准差与解更新缩放 |
SACauchy | learn_rate | 0.5 | 柯西扰动幅度缩放 |
一般调参思路:T_max应覆盖目标函数可能的函数值落差(决定初始"容忍坏解"程度);L决定每个温度下的精细度,越大越接近精确搜索但耗时更长;max_stay_counter用于提前终止,避免在低收益阶段空转。文档示例统一采用T_max=1, T_min=1e-9, L=300, max_stay_counter=150,对 demo 函数已足够收敛。
七、结果验证与收敛曲线绘制
run()结束后,可从对象属性中取出历史收敛数据并绘制曲线(examples/demo_sa.py):
import matplotlib.pyplot as plt import pandas as pd plt.plot(pd.DataFrame(sa.best_y_history).cummin(axis=0)) plt.show()其中best_y_history记录了每个降温周期(外层循环)的最优函数值,cummin取累计最小值后绘图,可以直观看到三种策略各自的收敛速度与最终精度,便于横向对比 Fast / Boltzmann / Cauchy 在具体问题上的表现。
八、延伸:SA 用于 TSP 组合优化
虽然 docs/en/more_sa.md 只介绍连续函数上的三种策略,但仓库将同一套 SA 骨架扩展到了组合优化——SA_TSP(sko/SA.py)。它以路径序列为解,每轮以等概率从三种变异算子中选择一种生成新路径:
swap:交换两个城市的访问顺序(sko/operators/mutation.py);reverse:反转一段子路径,即 2-Opt 思想(sko/operators/mutation.py);transpose:将一段子路径整体搬移到另一位置(sko/operators/mutation.py)。
用法示例(完整代码见 examples/demo_sa_tsp.py):
from sko.SA import SA_TSP sa_tsp = SA_TSP(func=cal_total_distance, x0=range(num_points), T_max=100, T_min=1, L=10 * num_points) best_points, best_distance = sa_tsp.run()其降温曲线为T_new = T_max / (1 + log(1 + k))(sko/SA.py),可借助best_x_history制作寻优过程动画。这也印证了"更换get_new_x与cool_down即可定制新的 SA 策略"的设计思路——三种连续策略与 TSP 版本本质上复用同一个SimulatedAnnealingBase骨架。
小结
- 三种策略选型:Fast 降温最快、适合快速粗寻优;Cauchy 重尾扰动、兼顾大范围跳变;Boltzmann 对数降温最慢、搜索最细致。三者均支持
lb/ub边界约束,解会被clip在界内; - 统一机制:Metropolis 准则、链长
L、温度区间[T_min, T_max]、max_stay_counter提前停止,构成三类算法的公共骨架(sko/SA.py); - 调参要点:Fast 调节
m/n/quench,Boltzmann 与 Cauchy 调节learn_rate;文档示例中的q参数在当前源码中不生效; - 实战入口:直接运行 examples/demo_sa.py 即可复现三策略全部示例,再结合
best_y_history绘制收敛曲线对比效果。
【免费下载链接】scikit-optGenetic Algorithm, Particle Swarm Optimization, Simulated Annealing, Ant Colony Optimization Algorithm,Immune Algorithm, Artificial Fish Swarm Algorithm, Differential Evolution and TSP(Traveling salesman)项目地址: https://gitcode.com/GitHub_Trending/sci/scikit-opt
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考