土木在线论坛 \ 建筑结构 \ 结构资料库 \ 最简单的元启发式算法-粒子群算法

最简单的元启发式算法-粒子群算法

发布于:2021-04-20 08:53:20 来自:建筑结构/结构资料库 [复制转发]

简介

粒子群算法(Particle Swarm Optimization,PSO)是解决优化问题的经典智能算法之一。

1995年,Eberhart和Kennedy从鸟群等群体社会模型中获得启发,抽象出粒子群算法,其特点是强调群体的信息共享。PSO概念简单,很容易与其他优秀的算法和技巧结合,被广泛应用于工程、计算机科学、行为管理科学等领域。

核心思想

粒子群可能是最简单的元启发式算法,我从一个简化的粒子群算法开始说明。

一开始,粒子在搜索空间中任意位置随机出生,每个粒子坐标都能计算出一个解,其中 最优解 的粒子坐标就是这个群体当前认为的最佳位置。

如果把这个 最优解 理解成食物最多,粒子群算法强调群体的直接信息共享,因此,所有粒子都立马知道了这里食物最多,全聚集过来了。

基础粒子群算法

在我看来,上述过程就是粒子群算法的核心。当然,作为一种目标是全局优化的算法,为了提高群体对搜索空间的探索能力,基础的粒子群算法除了 记忆 群体搜索时 历史最优位置 ,还会记忆个体在搜索时的历史最优位置。

这两个最优位置就像某种 引力源 ,使得粒子受到群体最佳和个体最佳的吸引。 形象地说,就是个体既会考虑集体的观点,也会相信自己的经验 。而全局优化算法必不可少的 随机因素 ,也主要体现在每次搜索时这两个引力源的 引力权重

这种直接牵引特点使得粒子群算法能够快速收敛,但也容易过早陷入局部最优。在粒子群算法的发展过程中,也引入了遗传算法中的进化等概念,以提高全局搜索能力。

说到这里,大家可能已经发现了元启发式算法的特点,确定简单但核心的启发思想后,开始加料,如增加随机因素,结合优秀的算法和技巧。元启发式算法的目标几乎都是找到全局最优,因此改进的方向大都是提高探索能力,避免过早陷入局部最优。

公式重构

我们接着聊基础的粒子群算法。依据前文所述的群体最佳和个体最佳两个要素,Eberhart和Kennedy给出的 粒子坐标更新公式 为:

其中 速度更新公式 为:

看得出来,他们俩写这个公式的时候就是原汁原味地把他们脑子想的搬出来了。在我眼里,这个公式其实与数值优化中的基本 迭代格式 非常相似:

这么一比,数值优化迭代格式的 和粒子群算法更新公式中的 直接对应上了。

我们从 信息 的角度来理解这个问题的本质。不管是粒子群优化还是数值优化,迭代方法都是逐个探索搜索空间中的坐标。我们把自己当做一个粒子,每迭代一次,就需要外界给出新的 指引信息 ,以帮助我们更好地去往下一个点,而不是瞎跑。自然,数值优化中指引方向的就是梯度等信息,而粒子群算法虽然没有高阶信息,但是有兄弟,其他人会告诉自己哪里食物更多。


既然两者的逻辑如此相似,我直接考虑对粒子群算法的速度更新公式进行了魔改,使得其更贴近熟悉的数值优化框架,便于理解。注意到速度更新公式中,本质上就是历史速度,个体最佳引力和全局最佳引力在争夺权重。根据概念不同,设:

其中global_weight就是全局最佳引力的权重,根据粒子群算法的设定,默认为0-1的随机值,也可以指定为固定值(如设置global_weight较大使得粒子偏向全局最佳靠近)。或者设计为与当前迭代次数相关,使得前期随机性强,后期确定性强。再有:

其中 是搜索步长,和数值优化一样,确定方向后,我们也可以进一步抉择在这个方向上走多远。有了这个概念后,甚至也可以在粒子群中引入线搜索确定步长的方法,或者AdaDelta等步长优化方法。

另外,其中history_weight是全局最佳引力的权重,根据粒子群算法的设定,大概为0.5,并将步长设定为2。对梯度下降法有一些了解的同学可能会发现,好家伙,这就是动量的概念啊。 后面这部分就是在权衡考虑多少历史速度,本质上是 指数移动平均方法 。由于保留了较多的历史速度,这可能是粒子群算法收敛较快,同时会产生震荡现象的原因。

至此,我们完成了对粒子坐标更新公式的重新理解,能够明白每个参数的设定会产生什么影响。

算法实现

理解了基本概念后,就可开始设计代码了。粒子的位置、速度等数据需要高频使用,故不考虑创建粒子个体对象,而是形成 粒子群整体的数据表

出于性能的需要,数据表并不是像结构体数组一样的整表,而是另写了一个由数组构成的类ParticleSwarm。ParticleSwarm应当提供粒子群数据的更新方法。通过python的魔法方法 __getitem__,也能很轻松地做到像整表索引一样获取每个粒子的信息。

另外再写一个ParticleSwarmOptimizer类型,用于记录优化器参数,定义优化逻辑,并提供基本的优化问题的接口 solve 。solve返回最终优化结果,其中callback可以接收优化过程的数据用于分析或可视化。

class ParticleSwarm: def __init__():        self.velocity        self.x        self.y        self.swarm_best        ...            def how_to_update_data():        ...class ParticleSwarmOptimizer:    def __init__(opt_parameters):        ...            def solve(func,bound,constraint,callback)->opt_result:        ...            def step(): # how_to_update_data        update_v()        update_x()        update_y()        update_swarm_best()        ...

省略亿点细节,我们写完了一个粒子群优化器,找几个函数看看优化过程有没有问题。

测试


branin

ackley

似乎还挺像那么回事,再用timeit测测速度。

在github上找到一个star比较高的包,比较下性能。

使用相同参数优化同一个问题,都设置为达到迭代次数上限,设置粒子数量50个:

嗯,也就快了3倍。

再设置粒子数量为500个:

快了18倍。差不多得了。



全部回复(0 )

只看楼主 我来说两句抢沙发
这个家伙什么也没有留下。。。

结构资料库

返回版块

41.19 万条内容 · 374 人订阅

猜你喜欢

阅读下一篇

建筑结构丨陶忠教授:木结构半榫节点加上阻尼器效果如何?试验揭秘!

[摘要] 为研究传统木结构半榫节点在改变木材种类、改变榫头宽度以及是否安装黏弹性阻尼器情况下的耗能能力,用松木和杉木制作了12个不同榫头宽度的半榫节点试件(6个未安装黏弹性阻尼器的节点试件和6个安装黏弹性阻尼器的节点试件),进行低周反复加载试验,并将6个未安装新型阻尼器的节点试件的试验结果与6个安装黏弹性阻尼器的节点试件的试验结果进行对比分析。研究结果表明:各半榫节点滞回曲线均呈反“Z”形,且捏缩效应明显,其中宽松节点滞回曲线产生较大的滑移;榫头宽度对半榫节点的骨架曲线斜率有较大影响,且增强后半榫节点推迟进入屈服阶段;紧密节点初始刚度最大,随加载的继续,各节点刚度下降后趋于平稳,增强后节点负向加载时刚度显著提高;安装黏弹性阻尼器的节点榫头拔榫量减小,同时节点的刚度、承载力和耗能能力得到有效增强。

回帖成功

经验值 +10