当前位置: 首页 > news >正文

模拟退火算法(Simulated Annealing):从物理学到优化的经典方法

模拟退火算法(Simulated Annealing):从物理学到优化的经典方法

作为一名熟悉大模型的研究者,你可能对深度学习中的梯度下降、Adam 优化等方法耳熟能详。但在阅读 Noise Conditioned Score Network (NCSN,参考笔者的博客:Denoising Score Matching:去噪分数匹配的优雅与实用性) 的退火朗之万采样时,可能会遇到“模拟退火”(Simulated Annealing, SA)这一术语。这是一个源于物理学的经典优化算法,虽然在现代深度学习中较少直接使用,但在理解退火类方法(如 NCSN 的采样)及其应用场景时非常有帮助。本篇博客将介绍模拟退火的原理、用途,并提供 Python 代码示例,帮助你快速掌握这一传统方法。

什么是模拟退火?

模拟退火算法灵感来源于物理学中的退火过程。退火是冶金学中的一种技术,通过将金属加热到高温后缓慢冷却,使其内部原子从无序状态逐渐排列为低能量、有序的晶体结构。模拟退火将这一过程类比为优化问题:

  • 高温阶段:系统处于高能量状态,允许探索解空间的各种可能性。
  • 冷却阶段:温度逐渐降低,系统趋向于收敛到低能量状态,即最优解。

在优化问题中,模拟退火的目标是寻找目标函数的最优解(通常是最小值),尤其适用于那些具有多局部最优解的复杂、非凸问题。

模拟退火的原理

假设我们要最小化一个目标函数 ( f ( x ) f(x) f(x) ),( x x x ) 是解空间中的一个状态。模拟退火的步骤如下:

  1. 初始化

    • 随机选择一个初始解 ( x 0 x_0 x0 )。
    • 设置初始温度 ( T 0 T_0 T0 )(通常较高)。
  2. 迭代更新

    • 在当前解 ( x t x_t xt ) 的邻域内随机生成一个新解 ( x ′ x' x )。
    • 计算能量差(目标函数的变化):( Δ E = f ( x ′ ) − f ( x t ) \Delta E = f(x') - f(x_t) ΔE=f(x)f(xt))。
    • 接受规则(Metropolis 准则)
      • 如果 ( Δ E ≤ 0 \Delta E \leq 0 ΔE0)(新解更优),接受 ( x ′ x' x ) 作为新解。
      • 如果 ( Δ E > 0 \Delta E > 0 ΔE>0)(新解更差),以概率 ( P = exp ⁡ ( − Δ E / T ) P = \exp(-\Delta E / T) P=exp(ΔE/T) ) 接受 ( x ′ x' x )。这允许算法跳出局部最优。
  3. 降温

    • 按照冷却策略(如 ( T t + 1 = α T t T_{t+1} = \alpha T_t Tt+1=αTt ),( α < 1 \alpha < 1 α<1))降低温度。
    • 温度越低,接受次优解的概率越小。
  4. 终止

    • 当温度降至某个阈值或达到最大迭代次数时,停止,返回当前解作为最优解。
关键特性
  • 随机性:通过随机扰动和概率接受机制,模拟退火可以探索解空间,避免陷入局部最优。
  • 温度控制:高温时更具探索性,低温时更倾向于收敛。
模拟退火有什么用?

模拟退火是一种全局优化算法,特别适合以下场景:

  1. 非凸优化问题
    • 当目标函数有多个局部最优解时(如旅行商问题 TSP、函数优化),梯度下降容易卡在局部极值,而模拟退火能跳出这些陷阱。
  2. 离散问题
    • 对于组合优化问题(如调度、图划分),解空间是离散的,模拟退火通过邻域搜索有效应对。
  3. 初始解不敏感
    • 与依赖初始值的局部搜索不同,模拟退火对初始解的依赖较低,适合未知领域的问题。
  4. 生成模型中的退火采样
    • 在 NCSN 等方法中,退火思想被用于从高噪声到低噪声逐步生成样本,模拟退火提供了一个类似的逐步优化框架。
Python 代码实现

以下是一个简单的模拟退火算法实现,用于最小化一个二维函数 ( f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2 )(全局最优解为 ( ( 0 , 0 ) (0, 0) (0,0) ))。

import numpy as np

# 目标函数:f(x, y) = x^2 + y^2
def objective_function(x):
    return x[0]**2 + x[1]**2

# 模拟退火算法
def simulated_annealing(initial_solution, initial_temp, cooling_rate, min_temp, max_iter):
    """
    Args:
        initial_solution: 初始解 (np.array)
        initial_temp: 初始温度
        cooling_rate: 冷却系数 (0 < cooling_rate < 1)
        min_temp: 最低温度
        max_iter: 每温度的最大迭代次数
    Returns:
        best_solution: 最优解
        best_value: 最优值
    """
    current_solution = initial_solution.copy()
    current_value = objective_function(current_solution)
    best_solution = current_solution.copy()
    best_value = current_value
    temp = initial_temp

    while temp > min_temp:
        for _ in range(max_iter):
            # 在邻域内随机生成新解
            perturbation = np.random.normal(0, 0.1, size=current_solution.shape)
            new_solution = current_solution + perturbation
            new_value = objective_function(new_solution)

            # 计算能量差
            delta_e = new_value - current_value

            # Metropolis 准则
            if delta_e <= 0 or np.random.rand() < np.exp(-delta_e / temp):
                current_solution = new_solution
                current_value = new_value

                # 更新最优解
                if current_value < best_value:
                    best_solution = current_solution.copy()
                    best_value = current_value

        # 降温
        temp *= cooling_rate

    return best_solution, best_value

# 主函数
def main():
    # 参数设置
    initial_solution = np.array([5.0, 5.0])  # 初始解
    initial_temp = 1000.0                    # 初始温度
    cooling_rate = 0.95                      # 冷却系数
    min_temp = 0.01                          # 最低温度
    max_iter = 100                           # 每温度迭代次数

    # 运行模拟退火
    best_solution, best_value = simulated_annealing(
        initial_solution, initial_temp, cooling_rate, min_temp, max_iter
    )

    print(f"最优解: {best_solution}")
    print(f"最优值: {best_value}")

if __name__ == "__main__":
    main()
代码说明
  1. 目标函数:这里用 ( f ( x , y ) = x 2 + y 2 f(x, y) = x^2 + y^2 f(x,y)=x2+y2 ) 作为示例,真实问题中可以替换为任何复杂函数。
  2. 邻域扰动:通过高斯噪声生成新解,模拟邻域搜索。
  3. Metropolis 准则:用 ( exp ⁡ ( − Δ E / T ) \exp(-\Delta E / T) exp(ΔE/T) ) 计算接受概率。
  4. 冷却策略:温度按 ( T = T × 0.95 T = T \times 0.95 T=T×0.95 ) 递减。

运行结果可能为:

最优解: [0.0123, -0.0087]
最优值: 0.000226

由于随机性,每次结果略有不同,但会接近全局最优解 ( ( 0 , 0 ) (0, 0) (0,0) )。

与 NCSN 的联系

NCSN 的退火朗之万采样从高噪声水平(如 ( σ 1 \sigma_1 σ1))到低噪声水平(如 ( σ L \sigma_L σL))逐步去噪,类似于模拟退火从高温到低温的优化过程:

  • 高温(大 ( σ \sigma σ)):允许大范围探索,生成粗略样本。
  • 低温(小 ( σ \sigma σ)):细化细节,逼近真实分布。

模拟退火的随机接受机制与朗之万动态中的噪声项有异曲同工之妙,都是为了跳出局部陷阱。

总结

模拟退火是一种经典的全局优化算法,通过模拟物理退火过程解决复杂优化问题。它在旅行商问题、调度优化等领域有广泛应用,并在生成模型的退火采样中提供了理论启发。虽然在深度学习中,它常被梯度方法取代,但在理解多尺度优化和随机搜索时仍具价值。希望这篇博客和代码能让你对模拟退火有个直观的认识!

后记

2025年3月8日16点40分于上海,在grok 3大模型辅助下完成。

相关文章:

  • leetcode刷题--超详解
  • 力扣203题:移除链表元素及代码实现分析
  • PAT线上考试注意细节(甲/乙级)
  • JDBC连接池技术详解
  • Linux网络基础
  • 【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解+代码解析]
  • 在人工智能软件的帮助下学习编程实例
  • 力扣 Hot 100 刷题记录 - 随机链表的复制
  • 力扣hot100——多维动态规划
  • 线性代数笔记28--奇异值分解(SVD)
  • 揭开AI-OPS 的神秘面纱 第四讲 AI 模型服务层(自研方向)
  • QT快速入门-信号与槽
  • 34.二叉树进阶3(平衡二叉搜索树 - AVL树及其旋转操作图解)
  • Flask框架中局部刷新页面
  • 北斗短报文+5G:遨游通信终端开启全域智能物联新时代
  • RAG技术的PDF智能问答系统
  • Effective Python:(18)作用域问题
  • 番外篇 - Docker的使用
  • VSCode 配置优化指南
  • 【从零开始学习计算机科学】硬件设计与FPGA原理
  • 中小企业网站建设与管理主要讲授什么/百度搜索关键词指数
  • 重庆网站建设 渝/开通网站需要多少钱
  • 网站建设的程序/seo外链代发
  • 物流企业网站有哪些/淘宝优秀软文范例100字
  • 域名到期网站/网站seo查询
  • 工业设计在线网站/百度总部