去年在研究群体智能算法时,我偶然发现了2019年提出的蝴蝶优化算法(BOA)。这个算法模拟蝴蝶通过气味寻找花蜜的行为,思路新颖但存在明显缺陷——就像一群没头苍蝇,经常在最优解附近打转却找不到准确位置。经过反复实验,我发现将PSO算法与混沌理论结合后,这群"智能蝴蝶"的寻优能力有了质的飞跃。
这次要复现的HPSBA算法,核心在于三个关键改进:Logistic混沌扰动像给蝴蝶安装了"随机振动器",自适应权重相当于"智能调速器",而PSO融合则是为蝴蝶群加入了"群体导航系统"。下面我会结合23个测试函数的实战数据,详细拆解每个改进点的实现细节。
混沌序列的特性非常适合优化算法——既不是完全随机,也不是简单周期,这种微妙的平衡能在不破坏收敛性的前提下增加多样性。我选择Logistic映射是因为它的计算简单且混沌特性明确:
python复制def logistic_chaos(n, mu=3.8):
x = np.zeros(n)
x[0] = np.random.rand()
for i in range(1, n):
x[i] = mu * x[i-1] * (1 - x[i-1])
return x
关键参数mu设置为3.8时,系统处于典型混沌状态。实验发现当mu<3.57时序列会周期性震荡,而mu>3.9又过于随机。
在算法后半程加入混沌扰动,相当于给陷入局部最优的蝴蝶一个"随机踢":
python复制if iteration > max_iter//2:
chaos_seq = logistic_chaos(pop_size)
gbest_pos = gbest_pos * (1 + 0.5*chaos_seq[np.argmin(fitness)])
实测在Rastrigin函数上,这种扰动能使收敛精度提升1-2个数量级。但要注意扰动强度系数0.5需要根据问题规模调整——对于100维以上的高维问题,建议降低到0.2-0.3。
传统BOA算法的一个缺陷是搜索步长固定,导致前期探索不足或后期震荡。受PSO惯性权重启发,我设计了这种非线性变化的自适应权重:
python复制w = w_max - (w_max - w_min) * (iteration/max_iter)**2
平方项的妙处在于:
在Griewank函数上的对比实验显示:
| 权重类型 | 收敛迭代数 | 最终精度 |
|---|---|---|
| 固定权重0.8 | 187 | 3.2e-4 |
| 线性递减 | 156 | 1.7e-5 |
| 非线性递减 | 132 | 9.3e-6 |
单纯的蝴蝶算法缺乏历史信息利用,就像没有记忆的觅食者。引入PSO的速度更新机制后,每只蝴蝶都能记住自己的最佳位置(pbest)并感知群体最佳(gbest):
python复制class Butterfly:
def __init__(self, dim):
self.velocity = np.zeros(dim) # 关键新增项
self.pbest_pos = self.position.copy()
def update_velocity(self, gbest_pos, w, c1=1.5, c2=1.5):
r1, r2 = np.random.rand(2)
self.velocity = w * self.velocity + c1*r1*(self.pbest_pos - self.position) + c2*r2*(gbest_pos - self.position)
self.position += self.velocity
在Ackley函数测试中,这种混合更新机制使算法成功跨越了多个周期性陷阱区域。特别值得注意的是认知系数c1和社会系数c2的设置——经过网格搜索验证,1.5-1.7是最佳区间,超过2.0会导致震荡。
python复制population = [Butterfly(dim) for _ in range(pop_size)]
gbest_pos = np.zeros(dim)
gbest_fitness = float('inf')
python复制w_max, w_min = 0.9, 0.4 # 惯性权重范围
mu = 3.8 # Logistic映射参数
c1, c2 = 1.5, 1.5 # PSO学习因子
实际应用中发现,对于高维问题(>100维),适当增大pop_size到50-100能显著提升效果
python复制for iter in range(max_iter):
# 1. 计算适应度并更新pbest/gbest
for butterfly in population:
fitness = evaluate(butterfly.position)
if fitness < butterfly.pbest_fitness:
butterfly.pbest_fitness = fitness
butterfly.pbest_pos = butterfly.position.copy()
if fitness < gbest_fitness:
gbest_fitness = fitness
gbest_pos = butterfly.position.copy()
# 2. 更新自适应权重
w = w_max - (w_max - w_min) * (iter/max_iter)**2
# 3. 更新蝴蝶位置(混合PSO机制)
for butterfly in population:
butterfly.update_velocity(gbest_pos, w, c1, c2)
# 4. 混沌扰动(后半程激活)
if iter > max_iter//2:
chaos_seq = logistic_chaos(pop_size)
gbest_pos = gbest_pos * (1 + 0.5*chaos_seq[np.argmin(fitness)])
除了常规的迭代次数限制,我还实现了两种智能停止条件:
python复制positions = np.array([b.position for b in population])
if np.std(positions) < 0.01 * (search_range[1] - search_range[0]):
break
选取了4类共23个标准测试函数:
特别加入了Schwefel 2.26这种具有欺骗性的函数——全局最优被多个局部最优包围,非常考验算法跳出能力
在D=30维度下,设置max_iter=300,pop_size=30的运行结果:
| 函数类型 | 指标 | BOA | HPSBA | 提升幅度 |
|---|---|---|---|---|
| 单峰 | 收敛迭代 | 152 | 89 | 41.4% |
| 多峰 | 最优精度 | 3.2e-3 | 6.5e-5 | 50倍 |
| 旋转 | 成功率 | 65% | 92% | +27% |
| 复合 | 平均误差 | 0.47 | 0.18 | 61.7% |
通过matplotlib动态展示算法过程,可以清晰看到:
python复制# 简易可视化代码示例
plt.ion()
for iter in range(max_iter):
positions = np.array([b.position for b in population])
plt.scatter(positions[:,0], positions[:,1], c='r')
plt.title(f'Iteration {iter}')
plt.draw()
plt.pause(0.1)
plt.clf()
通过控制变量测试mu参数的影响:
| mu值 | Lyapunov指数 | 收敛精度 |
|---|---|---|
| 3.5 | 0.12 | 2.4e-3 |
| 3.8 | 0.58 | 6.5e-5 |
| 4.0 | 0.72 | 3.1e-4 |
可见3.8确实是最佳平衡点,既保证足够混沌特性,又不会过度随机
对不同问题规模的推荐设置:
| 问题维度D | 建议pop_size | 迭代次数 |
|---|---|---|
| 10-30 | 20-30 | 200-300 |
| 30-100 | 30-50 | 300-500 |
| 100+ | 50-100 | 500-1000 |
对于高维问题,可以使用multiprocessing加速适应度计算:
python复制from multiprocessing import Pool
def parallel_evaluate(positions):
with Pool(4) as p:
return p.map(evaluate, positions)
实测在100维Ackley函数上,4进程可将单代计算时间从1.2s降至0.4s。
数值稳定性问题:
停止条件陷阱:
内存管理:
可视化技巧:
python复制# 内存优化示例
self.position = np.random.uniform(-5, 5, dim).astype(np.float32)
症状:群体快速聚集到非最优区域
解决方法:
症状:维度超过50后效果明显降低
优化策略:
症状:不同问题需要反复调参
自动化方案:
python复制# 自动调参示例
param_grid = {
'w_max': [0.7, 0.9],
'c1': [1.0, 1.5, 2.0]
}
best_params = grid_search(param_grid, objective_function)
最近我将算法扩展到了多目标优化版本(MOHPSBA),通过引入Pareto排序和非支配解归档机制,在ZDT测试函数集上表现优异。一个有趣的发现是:混沌扰动在多目标空间中能更好地维持解集多样性。