MOPSO多目标粒子群优化算法,可设置多个目标函数进行寻优,pbest更新采用支配方式更新,即下一个个体的所有目标优于上一个个体时进行更新,否则以一定概率更新;gbest采用非劣解方式进行更新,即所有个体的目标与第一个个体目标比较,最终确定非劣解集合
粒子群优化(PSO)玩过多目标版本的都知道,这玩意儿在解多目标问题的时候比传统算法更带劲儿。今天咱们就聊点MOPSO的骚操作——怎么让一群粒子在多个目标函数里找到最优解,还不打架。
MOPSO多目标粒子群优化算法,可设置多个目标函数进行寻优,pbest更新采用支配方式更新,即下一个个体的所有目标优于上一个个体时进行更新,否则以一定概率更新;gbest采用非劣解方式进行更新,即所有个体的目标与第一个个体目标比较,最终确定非劣解集合
先看pbest怎么玩。每个粒子都有自己的历史最优位置,但这里有个坑:不能只看单一目标函数。比如现在有两个目标,一个要成本最低,一个要性能最高。这时候新位置必须全面碾压旧位置才算更新。代码里判断支配关系的函数大概长这样:
def dominates(new_obj, old_obj): better_in_all = True for i in range(len(new_obj)): if new_obj[i] < old_obj[i]: # 假设都是最小化目标 better_in_all = False break return better_in_all但现实哪有那么多完美情况?当新解既不比旧的好,也不比旧的差的时候,咱们抛个硬币决定更不更新。这个随机性可以防止算法早熟:
if dominates(new_obj, current_pbest): update_pbest() elif random.random() < 0.5: # 50%概率强制更新 current_pbest = new_position重点来了,全局最优gbest怎么选?传统PSO直接选群体里最靓的仔,但多目标里根本没有绝对最优。这时候得建个非劣解档案馆。每代更新时,先把第一个粒子当标杆,其他粒子挨个和它比:
archive = [particles[0].position] for p in particles[1:]: is_dominated = False for a in archive: if dominates(a.objectives, p.objectives): is_dominated = True break if not is_dominated: archive.append(p.position) # 还要清理被新解支配的旧存档 archive = [a for a in archive if not dominates(p.objectives, a.objectives)]注意这里要动态维护存档,新解进来要踢掉被它支配的旧解。最后从存档里随机挑几个当gbest,这样能保证搜索方向的多样性。
速度更新还是经典公式,但位置越界时建议用反射边界处理,别直接卡死:
v = w*v + c1*rand()*(pbest_pos - x) + c2*rand()*(gbest_pos - x) x = x + v # 边界反射 for i in range(len(x)): if x[i] < lb[i]: x[i] = lb[i] + (lb[i] - x[i]) v[i] *= -0.5 elif x[i] > ub[i]: x[i] = ub[i] - (x[i] - ub[i]) v[i] *= -0.5最后给个实战建议:目标函数数量超过3个时,存档管理会指数级爆炸。这时候需要上自适应网格或者聚类算法来压缩存档规模,否则内存分分钟教你做人。参数设置也别死磕文献推荐值,不同问题的最优惯性权重可能差十倍,动手调参才是王道。