粒子群优化算法

本文作者为 360 奇舞团前端开发工程师

定义与基本原理

粒子群优化算法(Particle Swarm Optimization, PSO)是一种基于群体智能的元启发式优化算法,由James Kennedy和Russell Eberhart于1995年提出。该算法通过模拟鸟群、鱼群等生物群体的社会行为来解决复杂优化问题。在PSO中,每个"粒子"代表解空间中的一个潜在解决方案,粒子群体通过协作和信息共享在解空间中搜索最优解。

核心概念解析:

  1. 粒子:算法中的基本搜索单元,包含位置向量和速度向量

  2. 位置向量:表示粒子在当前解空间中的坐标(位置可以多维的),对应优化问题的一个候选解

  3. 速度向量:决定粒子在解空间中的移动方向和距离

  4. 个体最优解(pbest):每个粒子在搜索过程中找到的自身历史最优位置

  5. 群体最优解(gbest):整个粒子群迄今为止找到的最优位置

  6. 适应度函数:评估解决方案质量的函数,决定解的优劣(在下面的例子中就是求函数的值)

算法步骤详解

1. 初始化阶段

粒子群优化算法开始前需要设置关键参数并初始化粒子群:

  • 参数设置

    • 粒子数量:粒子越多越离散越好,但粒子越多,计算量就越大

    • 最大迭代次数:控制算法运行时间,也是结束条件之一,迭代次数越多准确性越高,计算量也就越大

    • 惯性权重:平衡全局和局部搜索能力

    • 学习因子:控制个体经验和社会经验的影响程度,包括个体学习因子和群体学习因子

    • 搜索边界:定义解空间的范围限制

  • 粒子初始化

    • 随机生成每个粒子的初始位置

    • 随机初始化粒子速度

    • 设置个体最优位置为初始位置

    • 计算初始适应度值

    • 确定初始全局最优位置

2. 迭代优化过程

粒子群通过以下步骤进行迭代搜索:

速度更新:

粒子速度由三部分组成:

  1. 惯性项:保持粒子原有运动趋势

  2. 认知项:引导粒子向自身历史最优位置移动

  3. 社会项:引导粒子向群体最优位置移动

速度更新公式:
新速度 = 惯性权重 × 当前速度 + 个体学习因子 × 随机数 × (个体最优位置 - 当前位置) + 群体学习因子 × 随机数 × (群体最优位置 - 当前位置)

位置更新:

粒子根据更新后的速度移动位置(多维的话,每个维度都要计算):
新位置 = 当前位置 + 新速度

边界处理:
  • 当粒子位置超出解空间边界时,采用反弹、吸收或周期性边界策略

  • 对速度进行限制,防止粒子移动过快导致振荡

适应度评估与最优更新:
  • 计算粒子新位置的适应度值

  • 若新适应度优于个体历史最优值,则更新个体最优位置

  • 若新适应度优于群体历史最优值,则更新群体最优位置

3. 终止条件与结果输出

算法在满足以下任一条件时终止:

  • 达到预设的最大迭代次数

  • 群体最优解连续多代无显著改进

  • 找到满足精度要求的最优解

最终输出:

  • 全局最优位置

  • 最优位置对应的最优解

算法简单案例

以下是一个简单的遗传算法实现,用于求解函数 f(x) = x + 10 * sin(5x) + 7 * cos(4x) 的最大值。

Figure_1.png
Figure_1.png
//粒子bean

publicclass Particle {
   privateint id;
   privatedouble position;
   privatedouble velocity;
   privatedouble pbestPos;
   privatedouble pbestVal; // 个体历史最优值

    public Particle(int id, double position, double velocity) {
        this.id = id;
        this.position = position;
        this.velocity = velocity;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public double getPosition() {
        return position;
    }

    public void setPosition(double position) {
        this.position = position;
    }

    public double getVelocity() {
        return velocity;
    }

    public void setVelocity(double velocity) {
        this.velocity = velocity;
    }

    public double getPbestPos() {
        return pbestPos;
    }

    public void setPbestPos(double pbestPos) {
        this.pbestPos = pbestPos;
    }

    public double getPbestVal() {
        return pbestVal;
    }

    public void setPbestVal(double pbestVal) {
        this.pbestVal = pbestVal;
    }
}



import java.util.ArrayList;
import java.util.List;
import java.util.Random;

publicclass PSOAlgorithm  {
    privateint numParticles = 100;  // 粒子数量
    privateint maxIterations = 60;  // 最大迭代次数
    privatefinaldouble initialW = 0.9;       // 初始惯性权重
    privatefinaldouble finalW = 0.1;         // 最终惯性权重
     privatedouble c1 = 1.5;          // 认知因子(增加到1.5)
    privatedouble c2 = 1.5;          // 社会因子(增加到1.5)
    privatedouble minPosition = -10; // 位置下限
    privatedouble maxPosition = 10;  // 位置上限
    privatedouble maxVelocity = 2;   // 最大速度限制
    private List<Particle> particles = new ArrayList<>();
    privatedouble globalBestValue = Double.NEGATIVE_INFINITY; // 初始化为最小值
    privatedouble globalBestPosition = 0; // 全局最优位置


    // 目标函数:求解 f(x) = x + 10*sin(5*x) + 7*cos(4*x) 的最大值
    public   double fitnessFunction(double x) {
        return x + 10 * Math.sin(5 * x) + 7 * Math.cos(4 * x);
    }
public void runPSO() {
        initParticles();
     particleSwarmOptimization();
     printFinalResult();


 }
    private void printFinalResult() {
        System.out.println("\n===== 优化结果 =====");
        System.out.printf("全局最优位置: x = %.4f\n", globalBestPosition);
        System.out.printf("全局最优值: f(x) = %.4f\n", globalBestValue);
        System.out.println("函数验证: " + fitnessFunction(globalBestPosition));
    }
    //初始化粒子群
   private void initParticles(){
       particles.clear();
       globalBestValue = Double.NEGATIVE_INFINITY;
       globalBestPosition = 0;
       Random random = new Random();
       for (int i = 0; i < numParticles; i++) {
           double position = minPosition + random.nextDouble() * (maxPosition - minPosition);
           double velocity = -maxVelocity + random.nextDouble() * (2 * maxVelocity);
           particles.add(new Particle(i, position, velocity));
           particles.get(i).setPosition(position);
           particles.get(i).setPbestVal(fitnessFunction(position));
           // 初始化全局最优
           if (particles.get(i).getPbestVal() > globalBestValue) {
               globalBestValue = particles.get(i).getPbestVal();
               globalBestPosition = position;
           }
       }


   }

    private  void particleSwarmOptimization() {
        finaldouble convergenceThreshold = 0.0000001;
        int noImprovementCount = 0;
        double prevBest = globalBestValue;
        System.out.println("===== 粒子群优化开始 =====");
        System.out.println("目标: 求解 f(x) = x + 10*sin(5*x) + 7*cos(4*x) 在区间["+minPosition+", "+maxPosition+"]的最大值");
        System.out.println("粒子数: " + numParticles + ", 最大迭代次数: " + maxIterations);
        System.out.println("参数: w=[" + initialW + "→" + finalW + "] c1=" + c1 + " c2=" + c2);
        Random random = new Random();
        for (int iteration = 0; iteration < maxIterations; iteration++) {


            double w = initialW - (initialW - finalW) * iteration / maxIterations;


            for (Particle particle : particles) {

                // 1. 速度更新
                double r1 = random.nextDouble();
                double r2 = random.nextDouble();
                double cognitiveComponent = c1 * r1 * (particle.getPbestPos() - particle.getPosition());
                double socialComponent = c2 * r2 * (globalBestPosition - particle.getPosition());

                double newVelocity = w * particle.getVelocity() + cognitiveComponent + socialComponent;

                // 限制速度范围
                if (newVelocity > maxVelocity) newVelocity = maxVelocity;
                if (newVelocity < -maxVelocity) newVelocity = -maxVelocity;

                particle.setVelocity(newVelocity);

                // 2. 位置更新
                double newPosition = particle.getPosition() + newVelocity;

                // 限制位置范围
                if (newPosition > maxPosition) newPosition = maxPosition;
                if (newPosition < minPosition) newPosition = minPosition;

                particle.setPosition(newPosition);

                // 3. 评估当前位置
                double currentValue = fitnessFunction(particle.getPosition());

                // 4. 更新个体最优(求最大值所以用 > )
                if (currentValue > particle.getPbestVal()) {
                    particle.setPbestVal(currentValue);
                    particle.setPbestPos(particle.getPosition());

                    // 5. 更新全局最优
                    if (currentValue > globalBestValue) {
                        globalBestValue = currentValue;
                        globalBestPosition = particle.getPbestPos();
                    }
                }
            }

            System.out.printf(" 迭代轮次 %d/%d, 当前最优: f(%.4f) = %.4f%n",
                    iteration + 1, maxIterations,
                    globalBestPosition, globalBestValue);
            if (Math.abs(globalBestValue - prevBest) < convergenceThreshold) {
                noImprovementCount++;
                if (noImprovementCount >= 15) {
                    System.out.println("\n早停触发: 连续15次迭代改进<"+convergenceThreshold);
                   break;
                }
            } else {
                noImprovementCount = 0;
                prevBest = globalBestValue;
            }
        }

    }

    public static void main(String[] args) {
        PSOAlgorithm optimization = new PSOAlgorithm();
        optimization.runPSO();
    }
}
===== 粒子群优化开始 =====
目标: 求解 f(x) = x + 10*sin(5*x) + 7*cos(4*x) 在区间[-10.0, 10.0]的最大值
粒子数: 140, 最大迭代次数: 60
参数: w=[0.9→0.1] c1=1.5 c2=1.5
 迭代轮次 1/60, 当前最优: f(7.8729) = 24.8084
………………省略一些输出…………

 迭代轮次 24/60, 当前最优: f(7.8566) = 24.8554

早停触发: 连续15次迭代改进<1.0E-7

===== 优化结果 =====
全局最优位置: x = 7.8566
全局最优值: f(x) = 24.8554
函数验证: 24.855360659875842

算法特性分析

核心优势:

  1. 实现简单:算法结构清晰,参数较少

  2. 收敛速度快:初期收敛效率高

  3. 并行性强:粒子可独立计算,适合并行处理

  4. 无需梯度信息:对目标函数要求低

  5. 全局搜索能力强:能有效避免局部最优陷阱

局限性:

  1. 参数敏感:性能受参数设置影响较大

  2. 早熟收敛:可能陷入局部最优

  3. 理论分析困难:收敛性证明复杂

  4. 离散问题局限:对组合优化问题效果有限

参数选择策略

关键参数:

参数

作用

推荐范围

设置建议

粒子数量

影响搜索能力

20-100

问题越复杂,粒子数越多

惯性权重

平衡全局/局部搜索

0.4-0.9

采用线性递减策略

个体因子(c1)

控制个体经验影响

1.5-2.0

与c2保持平衡

群体因子(c2)

控制群体经验影响

1.5-2.0

大于c1增强全局搜索

最大速度

限制粒子移动步长

解空间范围10%-20%

防止振荡

总结

粒子群优化算法是一种受自然启发的高效优化方法,它通过模拟群体中个体之间的信息共享机制,使整个群体逐渐逼近最优解。虽然其理论基础不如传统数学优化方法严谨,但在实际工程和科研中表现出良好的鲁棒性和实用性。

-END -

如果您关注前端+AI 相关领域可以扫码进群交流

添加小编微信进群😊

关于奇舞团

奇舞团是 360 集团最大的大前端团队,非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值