智能算法系列之粒子群优化算法

2023-10-31

在这里插入图片描述

  本博客封面由ChatGPT + DALL·E 2共同创作而成。

前言

  本篇是智能算法(Python复现)专栏的第三篇文章,主要介绍粒子群优化算法(ParticleSwarm Optimization, PSO)的思想,python实现及相关应用场景模拟。

  粒子群优化算法,简称粒子群算法,也叫作鸟群觅食算法。PSO算法的基本思想受到许多对鸟类的群体行为(觅食行为)进行建模与仿真研究结果的启发,粒子在解空间中追随最优的粒子进行迭代搜索,而不需要像遗传算法那样使用交叉以及变异操作。

1. 算法思想

  PSO算法最初设想是模拟鸟群觅食的过程,想象这样一个场景:一群鸟随机的分布在一个区域,在这个区域只有一块食物,但是所有的鸟都不知道这块食物的具体方位,只知道自己当前的位置距离食物还有多远。找到食物最简单有效的方式就是搜索目前离食物最近的鸟的周围区域。如果把食物当作最优点,而把鸟离食物的距离当作函数的适应度,那么鸟寻觅食物的过程就可以当作函数寻优的过程。由此受到启发,经过简化提出了PSO算法。

  PSO算法作为一种仿生算法,目前还没有完备的数学理论作为基础,但是作为一种新兴的智能优化算法,已经在诸多领域展现了良好的应用前景。

  粒子群优化算法的核心思想是通过模拟鸟群或鱼群等动物的群体行为,以达到求解最优化问题的目的。在粒子群优化中,搜索空间中的每个解都被视为一个粒子,每个粒子的位置表示解的搜索空间中的位置,粒子的速度表示解的搜索方向和速度。在搜索过程中,每个粒子通过学习其他粒子的经验,更新自己的位置和速度。粒子的位置和速度的更新可以分为两个部分:局部搜索和全局搜索。局部搜索是指粒子在其自身经验的基础上进行搜索,全局搜索是指粒子在全局最优解的基础上进行搜索。具体来说,每个粒子会记忆其历史最优解和全局最优解,然后通过调整自己的速度和位置来寻找更好的解。
  粒子群优化算法的基本步骤如下:
  (1) 初始化粒子群:随机生成粒子群中每个粒子的位置和速度。
  (2) 计算每个粒子的适应度:根据粒子的位置计算适应度函数的值。
  (3) 更新每个粒子的历史最优解:将粒子自己的历史最优解更新为当前最优解。
  (4) 更新全局最优解:将整个粒子群的最优解更新为所有粒子历史最优解中最优的一个。
  (5) 更新每个粒子的速度和位置:根据当前粒子自己的历史最优解和整个粒子群的最优解,以及粒子的速度和位置,更新粒子的速度和位置。
  粒子的速度更新公式如下: v ( t + 1 ) = v ( t ) + c 1 r 1 ( t ) [ p b e s t ( t ) − x ( t ) ] + c 2 r 2 ( t ) [ g b e s t ( t ) − x ( t ) ] v(t+1) = v(t) + c_1r_1(t)[pbest(t) - x(t)] + c_2r_2(t)[gbest(t) - x(t)] v(t+1)=v(t)+c1r1(t)[pbest(t)x(t)]+c2r2(t)[gbest(t)x(t)]  其中 c 1 c_1 c1 c 2 c_2 c2表示学习因子,也叫加速因子,具体来说, c 1 c_1 c1用来调节粒子飞向自身最好位置方向的步长, c 2 c_2 c2用来调节粒子飞向全局最好位置方向的步长。 r 1 r_1 r1 r 2 r_2 r2用来保持群体的多样性。 p b e s t pbest pbest表示当前粒子迄今为止搜索到的最优位置, g b e s t gbest gbest为整个粒子群迄今为止搜索到的最优位置。
  粒子的位置更新公式如下: x ( t + 1 ) = x ( t ) + v ( t + 1 ) x(t+1) = x(t) + v(t+1) x(t+1)=x(t)+v(t+1)

在这里插入图片描述

2. 细节梳理

2.1 超参数的选择

  PSO算法中没有实际的机制来控制粒子速度,值太大会导致粒子跳过最好解,太小又会导致对搜索空间的不充分搜索,所以有必要对速度的范围进行限制,一般可以根据搜索的位置范围进行调节,比如,本示例中的搜索范围为[0, 5],粒子的速度范围为[-1, 1]
   c 1 c_1 c1 c 2 c_2 c2这两个参数对粒子群算法的收敛起的作用不是很大,但是适当调整这两个参数,可以减小局部最小值的困扰,当然也会使收敛速度变快。
   r 1 r_1 r1 r 2 r_2 r2可以设置为[0,1]的随机数。

2.2 一些trick

  为了改善基本PSO算法的收敛性能,在更新粒子的速度时引入了惯性权重的概念,即: v ( t + 1 ) = w v ( t ) + c 1 r 1 ( t ) [ p b e s t ( t ) − x ( t ) ] + c 2 r 2 ( t ) [ g b e s t ( t ) − x ( t ) ] v(t+1) = wv(t) + c_1r_1(t)[pbest(t) - x(t)] + c_2r_2(t)[gbest(t) - x(t)] v(t+1)=wv(t)+c1r1(t)[pbest(t)x(t)]+c2r2(t)[gbest(t)x(t)]  其中, w w w称为惯性权重,基本PSO算法是惯性权重 w = 1 w=1 w=1的特殊情况。惯性权重 w w w使粒子保持飞行惯性,使其可以扩展搜索空间,有能力探索新的区域。

  带有惯性权重的粒子群优化算法是最常用的一种粒子群优化算法,本示例就是基于带有惯性权重的粒子群优化算法进行实现的。

  惯性权重 w w w的引入清除了基本PSO算法对速度最大值的需求,因为 w w w的作用就是保持全局和局部搜索能力的平衡。当速度最大值增加时,就人为减少 w w w来达到搜索的平衡,而 w w w的减少可降低需要的迭代次数,就可以将某一维速度的最大值锁定为每维变量的变化范围,只对 w w w进行调节。
  对全局搜索,广泛使用的方法是在前期利用较高的探索能力得到具有超高潜力且多样化的种子,而在后期提升开发能力以加快收敛速度,所以,也可以将 w w w设定为随进化迭代次数线性减少[在本示例中未实现该操作]

  除了上述的改进算法外,还有协同粒子群优化算法、量子粒子群优化算法(Qutantum-behaved Particle SwarmOptimization,QPSO)和混合粒子群优化算法。其中混合粒子群优化算法的研究更为广泛,小博主我计划在下一篇中介绍一下基于模拟退火算法的粒子群优化算法,其性能比单纯的模拟退火算法和粒子群优化算法都要好,敬请期待。

3. 算法实现

3.1 问题场景

  最值问题,求解 f ( x ) = x s i n ( 5 x ) − x c o s ( 2 x ) f(x) = xsin(5x) - xcos(2x) f(x)=xsin(5x)xcos(2x)在定义域[0, 5]上的最小值。我们先手动计算一下:

f ′ ( x ) = 2 x s i n ( 2 x ) + s i n ( 5 x ) − c o s ( 2 x ) + 5 x c o s ( 5 x ) f^\prime (x) = 2 x sin(2 x) + sin(5 x) - cos(2 x) + 5 x cos(5 x) f(x)=2xsin(2x)+sin(5x)cos(2x)+5xcos(5x)  令 f ′ ( x ) = 0 f^\prime (x) = 0 f(x)=0之后,理论上可以求得驻点,但又不太好计算。。。

3.2 python实现

# -*- coding:utf-8 -*-
# Author:   xiayouran
# Email:    youran.xia@foxmail.com
# Datetime: 2023/3/16 16:54
# Filename: particle_swarm_optimization.py
import numpy as np
import matplotlib.pyplot as plt
from base_algorithm import BaseAlgorithm
# base_algorithm 的实现已开源在github上
# 链接在文章末尾


__all__ = ['ParticleSwarmOptimization']


class Particle:
    def __init__(self):
        self.position = None    # 粒子的位置
        self.velocity = None    # 粒子的速度
        self.best_position = None   # 个体最优解
        self.fitness = None         # 适应度值


class ParticleSwarmOptimization(BaseAlgorithm):
    def __init__(self, population_size=100, p_dim=1, v_dim=1, max_iter=1000, x_range=(0, 5), seed=10086):
        super(ParticleSwarmOptimization, self).__init__()
        self.__population_size = population_size  # 种群大小
        self.__p_dim = p_dim        # 粒子位置维度
        self.__v_dim = v_dim        # 粒子速度维度
        self.__max_iter = max_iter  # 最大迭代次数
        self.__w = 0.5    # 惯性权重
        self.__c1 = 1.5   # 加速因子1
        self.__c2 = 1.5   # 加速因子2
        self.__population = []    # 粒子群
        self.global_best_particle = None    # 全局最优解
        self.__x_range = x_range
        self.__seed = seed

        np.random.seed(seed)

    def init_population(self):
        for i in range(self.__population_size):
            particle = Particle()
            particle.position = np.random.uniform(*self.__x_range, size=self.__p_dim)   # 随机初始化位置
            particle.velocity = np.random.uniform(-1, 1, size=self.__v_dim)     # 随机初始化速度
            particle.best_position = particle.position  # 初始最优位置
            particle.fitness = self.problem_function(particle.position)     # 计算适应度值
            if self.global_best_particle is None or particle.fitness < self.problem_function(self.global_best_particle.position):
                self.global_best_particle = particle  # 更新全局最优解
            self.__population.append(particle)

    def update_population(self):
        for i in range(self.__population_size):
            particle = self.__population[i]
            r1 = np.random.uniform(0, 1)
            r2 = np.random.uniform(0, 1)
            # Step2: 更新速度
            particle.velocity = self.__w * particle.velocity + \
                                self.__c1 * r1 * (particle.best_position - particle.position) + \
                                self.__c2 * r2 * (self.global_best_particle.position - particle.position)
            # Step3: 更新位置
            particle.position += particle.velocity
            particle.position = np.clip(particle.position, 0, 5)
            # Step4: 更新个体最优解
            if self.problem_function(particle.position) < self.problem_function(particle.best_position):
                particle.best_position = particle.position
                particle.fitness = self.problem_function(particle.position)
            # Step5: 更新全局最优解
            if self.problem_function(particle.position) < self.problem_function(self.global_best_particle.position):
                self.global_best_particle = particle

    def solution(self):
        # Step1: 粒子初始化
        self.init_population()
        for i in range(self.__max_iter):
            self.update_population()
        print('best particle:\nposition: {}\nvelocity: {}'
              '\nfitness: {}\nbest_position: {}'.format(self.global_best_particle.position,
                                                        self.global_best_particle.velocity,
                                                        self.global_best_particle.fitness,
                                                        self.global_best_particle.best_position))

if __name__ == '__main__':
    algo = ParticleSwarmOptimization()
    algo.solution()

  得到的最优解如下:

best particle:
position: [3.43298001]
velocity: [1.10173139e-09]
fitness: [-6.27707976]
best_position: [3.43298001]

  模拟过程如下:

在这里插入图片描述

代码仓库:IALib[GitHub]

  本篇代码已同步至【智能算法(Python复现)】专栏专属仓库:IALib
  运行IALib库中的PSO算法:

git clone git@github.com:xiayouran/IALib.git
cd examples
python main.py -algo pso
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

智能算法系列之粒子群优化算法 的相关文章

随机推荐

  • js提示“没有权限”的问题(转载)

    当某个互联网运营商的网站上规模之后 他们都会考虑将网站部署到主域名相同 子域名不同的服务器集群上 以此来构建一个聚合的应用 同时 希望能够利用 JavaScript 在不同子域的网页间相互操作 实现一个对用户来说 无缝 的应用 这时 跨域操
  • 我是如何用 redis 分布式锁来解决线上历史业务问题的

    近期发现 开发功能的时候发现了一个 mq 消费顺序错乱 历史遗留问题 导致业务异常的问题 看看我是如何解决的 问题抛出 首先 简单介绍一下情况 线上 k8s 有多个 pod 会去消费 mq 中的消息 可是生产者发送的消息是期望一定要有序去消
  • HTML5 postMessage和跨域通信

    HTML5 postMessage和跨域通信 http iknowledge wikispaces com HTML5 postMessage E5 92 8C E8 B7 A8 E5 9F 9F E9 80 9A E4 BF A1 HTM
  • stm32cubemx hal学习记录:FreeRTOS中断管理

    一 参数配置 1 配置RCC USART1 时钟84M 2 配置SYS 将Timebase Source修改为除滴答定时器外的其他定时器 3 初始化LED的两个引脚 两个按键引脚 4 开启FreeRTOS v1与v2版本不同 一般选用v1即
  • 梯度下降法及其Python实现

    梯度下降法 gradient descent 又名最速下降法 steepest descent 是求解无约束最优化问题最常用的方法 它是一种迭代方法 每一步主要的操作是求解目标函数的梯度向量 将当前位置的负梯度方向作为搜索方向 因为在该方向
  • 轻松玩转开源大语言模型bloom(一)

    前言 chatgpt已经成为了当下热门 github首页的trending排行榜上天天都有它的相关项目 但背后隐藏的却是openai公司提供的api收费服务 作为一名开源爱好者 我非常不喜欢知识付费或者服务收费的理念 所以便有决心写下此系列
  • Vue3最常见的10道面试题:含答案和代码示例的练习题

    本文列举了10道Vue3面试题 每道题都包含了答案和代码示例 希望对你的面试有所帮助 什么是Vue3 Vue3是Vue js的下一个主要版本 它带来了很多重要的改进和新功能 包括更快的渲染速度 更好的类型支持 更好的组合API等 什么是Co
  • Postman 如何调用文件上传下载接口

    文件导入导出是管理后台的通用功能 所以在接口写好后在没有前端页面使用Postman进行接口调用测试接口功能成为一个选择 导出 在我们输入接口地址 token等候 点击send 发现下载的成为了乱码 如下图 这明显不符合我们的预期期望 在se
  • 文本分析简历项目收集-----机器学习(仅供参考)

    文本分析 项目3 基于自然语言处理的影评分析 项目简介 通过大量的正面和负面的电影评论对计算机进行自然语言训练 实现计算机对电影评论的基本情感分析 使其能够快速判断出评论是否积极 个人职责 1 对正面和负面的电影评论进行分词处理 整理成规定
  • 一次让人难以忘怀的排查频繁Full GC过程

    我们的Java应用因频繁FULL GC导致性能降低很多 经过多人的定位也没有结论 于是我自主请命 经过一天的研究终于搞定了 现把经验与大家共享 相关的gc日志如下 4 758 Full GC PSYoungGen 464K gt 0K 71
  • linux统计一个文件中特定字符的个数

    统计一个文件中某个字符串的个数 其实就是在在一块沙地里面找石头 有的人看到石头以后 在上面做个标记 grep 然后记住自己做了多少个标记 有的 人看到石头以后 把它挖了 tr 最后统计自己挖了多少石头 有的人看到石头以后 把它跳过去 awk
  • STL:list的模拟实现(迭代器失效探讨)

    为什么重新设计list迭代器 对迭代器解引用 我们希望拿到的是指针所指向的值域 而直接解引用拿到的是指针所指向的节点 对list指针 和 迭代器 提供一种方法 使其能够按照顺序访问容器 聚合物 所含的各个元素 并且不用暴露容器内部的表述方式
  • 达芬奇15中文版

    教程 1 下载解压 得到davinci resolve 15原程序和文件 2 双击文件 DaVinci Resolve Studio 15 0b2 Windows exe 依提示安装原程序 3 达芬奇软件需要安装必要的组件 一般按默认安装即
  • Flexible弹性布局

    flex布局 弹性布局 flex的两个重要概念 开启了flex布局的元素叫flex container display flex inline flex flex container 里面的直接子元素叫做 flex items flex布局
  • 来源查询检索的研究

    来源查询检索的研究 来源查询的方式主要有 基于内容索引的查询 gt 基于时间局部性的上下文增强搜索查询 gt 基于因果关系的查询 根据provenance提供上下文有关的索引 即因果关系 1 传统的来源查询检索方式为基于内容索引的查询 在这
  • 阿里云视频点播文件上传-iOS

    文章目录 阿里云视频点播文件上传 iOS 一 上传方式 方式一 上传地址加凭证上传 1 请求AppServer 2 在start的回调中设置上传地址和上传凭证 3 uploadAuth过期重新设置 4 上传图片和上传视频 方式二 STS方式
  • 记一次线上CPU持续飙升的问题排查

    最近公司的事务多了很多 都很少有时间来更新了 上周六项目上刚刚发生了一次CPU持续飙高 导致服务不可用的线上事故 在此也简单做下记录 问题排查的过程大概是这样的 查看业务日志中最开始报错的信息 发现数据库连接超时 redis也连接超时 而且
  • 嵌入式实践——烟雾产生器

    开发工具 Altium Designer 2020 STM32CubeMX 5 3 0 MDK ARM 5 28 1 设计需求 设计出一套完整的烟雾产生装置 该装置通过按钮来控制烟雾的产生和关闭 装置对体积要求较高 所以控制板需控制在4cm
  • WPF 文本框错误验证 Validation.ErrorTemplate

    前端 1 错误模板ValidationContent xaml
  • 智能算法系列之粒子群优化算法

    本博客封面由ChatGPT DALL E 2共同创作而成 文章目录 前言 1 算法思想 2 细节梳理 2 1 超参数的选择 2 2 一些trick 3 算法实现 3 1 问题场景 3 2 python实现 代码仓库 IALib GitHub