第2章 全局优化算法基础:GA、PSO、SA原理
全局优化算法,说白了就是一群「不撞南墙不回头」的搜索策略。它们的目标很明确——在巨大的搜索空间里,找到那个全局最优解。我做了这么多年优化,见过太多人一上来就调参,结果连算法原理都没搞明白。今天咱们就把遗传算法、粒子群优化、模拟退火这三个老大哥讲透。
核心认知:这三种算法都不是「万能钥匙」。GA擅长离散组合优化,PSO在连续空间里跑得快,SA适合跳出局部陷阱。选对工具比调好参数重要十倍。
2.1 遗传算法(GA)——进化论的工程实现
遗传算法的灵感来自达尔文的自然选择。我当年第一次看到这个算法时,心里想的是:「这不就是代码版的物种进化吗?」
2.1.1 核心流程
- 编码:把问题的解表示成「染色体」。二进制编码最常见,但实数编码在连续问题上更直接。
- 初始化种群:随机生成N个个体。N太小容易早熟,N太大计算量爆炸。我个人习惯取50-200之间。
- 适应度评估:算每个个体的好坏。适应度函数就是你的目标函数,但要注意——GA默认找最大值,如果是最小化问题,得做个变换。
- 选择:优胜劣汰。轮盘赌、锦标赛、排名选择,各有各的脾气。
- 交叉:两个父代交换基因片段。单点交叉、多点交叉、均匀交叉,交叉概率一般设0.7-0.9。
- 变异:随机改变基因。变异概率通常很小,0.01-0.1。太大了就变成随机搜索了。
- 迭代:重复3-6步,直到满足终止条件。
我曾经踩过的坑:有一次做车间调度优化,我把变异概率设成了0.3,结果算法跑了100代还在震荡,根本收敛不了。后来改成0.05,效果立竿见影。记住——变异是「扰动」,不是「主引擎」。
2.1.2 关键参数速查表
| 参数 | 典型范围 | 我的建议 |
|---|---|---|
| 种群大小 | 20-200 | 问题维度高就取大值 |
| 交叉概率 | 0.6-0.95 | 别低于0.6,否则搜索太慢 |
| 变异概率 | 0.01-0.1 | 先试0.05,再微调 |
| 精英保留数 | 1-5 | 保留最优个体,防止退化 |
2.1.3 代码骨架
def genetic_algorithm(fitness_func, dim, pop_size=100, max_gen=500):
# 初始化种群
pop = np.random.uniform(low, high, (pop_size, dim))
for gen in range(max_gen):
# 评估适应度
fitness = np.array([fitness_func(ind) for ind in pop])
# 选择(锦标赛)
new_pop = []
for _ in range(pop_size):
i, j = np.random.choice(pop_size, 2, replace=False)
winner = pop[i] if fitness[i] > fitness[j] else pop[j]
new_pop.append(winner)
# 交叉(模拟二进制交叉)
# 变异(多项式变异)
# 精英保留
return best_individual
2.2 粒子群优化(PSO)——鸟群的数学建模
PSO是我个人最喜欢的算法之一。为什么?因为它简单、参数少、收敛快。你想想看,一群鸟在找食物,每只鸟既记得自己找到过的最好位置,也参考同伴们发现的最好位置。这不就是分布式智能吗?
2.2.1 核心公式
每个粒子有两个属性:位置 x 和速度 v。更新规则就两条:
v[i] = w * v[i] + c1 * r1 * (pbest[i] - x[i]) + c2 * r2 * (gbest - x[i])
x[i] = x[i] + v[i]
这里:
w:惯性权重。控制全局搜索和局部搜索的平衡。我习惯从0.9线性递减到0.4。c1, c2:学习因子。一般取2.0,但也可以调。r1, r2:[0,1]的随机数。pbest:个体历史最优。gbest:全局最优。
小技巧:速度一定要限幅!我见过有人没加速度上限,结果粒子直接飞出天际,解的质量一塌糊涂。一般设位置范围的10%-20%作为速度上限。
2.2.2 PSO vs GA
| 对比维度 | PSO | GA |
|---|---|---|
| 信息共享 | 单向(gbest引导) | 双向(交叉交换) |
| 参数数量 | 3-4个 | 5-7个 |
| 收敛速度 | 快,但易早熟 | 慢,但更稳健 |
| 适用场景 | 连续优化 | 离散/组合优化 |
2.3 模拟退火(SA)——炼钢工人的智慧
模拟退火的物理背景很有意思。金属加热后慢慢冷却,原子会排列成能量最低的晶体结构。算法就是模仿这个过程——高温时允许「坏解」,低温时只接受「好解」。
2.3.1 核心机制
- 初始温度T₀:设得足够高,保证初期能接受大部分差解。
- 扰动:在当前解附近随机生成一个新解。
- 接受准则(Metropolis准则):
- 如果新解更好,直接接受。
- 如果新解更差,以概率
exp(-ΔE/T)接受。
- 降温:T = α * T,α通常取0.85-0.99。
- 终止:温度降到接近0,或者连续多次没有改进。
我曾经犯过的错:有一次做旅行商问题,我把降温系数设成了0.95,结果跑了2万次迭代还没收敛。后来改成0.99,虽然迭代次数多了,但解的质量明显提升。记住——降温越慢,搜索越充分,但时间成本也越高。
2.3.2 参数设置指南
| 参数 | 作用 | 经验值 |
|---|---|---|
| 初始温度T₀ | 控制初期接受概率 | 使接受概率≈0.8 |
| 降温系数α | 控制降温速度 | 0.85-0.99 |
| 每个温度迭代次数 | 平衡搜索充分性 | 100-1000 |
| 终止温度 | 停止条件 | 1e-5 或更小 |
2.4 三种算法的知识图谱
下面这张图把GA、PSO、SA的核心逻辑串起来了。你仔细看,它们其实都在做同一件事——「探索 vs 利用」的权衡。
2.5 选型建议
到底用哪个?我个人的经验是:
- 离散组合问题(排班、路径规划、调度):优先GA。它的交叉操作天然适合组合结构。
- 连续函数优化(参数调优、神经网络训练):优先PSO。收敛快,代码简单。
- 解空间极其崎岖(多峰函数、能量景观复杂):优先SA。它的概率接受机制不容易被困住。
- 时间充裕、追求高质量解:混合策略。比如先用GA跑几代,再用PSO精调,最后用SA跳出局部。
我的一个实战案例:去年做天线阵列优化,搜索空间有50个维度,而且是个多峰问题。我试了纯PSO,早熟严重;纯GA,收敛太慢。最后用GA做全局探索(50代),再用PSO做局部精化(100代),效果比单独用任何一个都好。这就是协同策略的价值。