本文作者为 360 奇舞团前端开发工程师
定义与基本原理
粒子群优化算法(Particle Swarm Optimization, PSO)是一种基于群体智能的元启发式优化算法,由James Kennedy和Russell Eberhart于1995年提出。该算法通过模拟鸟群、鱼群等生物群体的社会行为来解决复杂优化问题。在PSO中,每个"粒子"代表解空间中的一个潜在解决方案,粒子群体通过协作和信息共享在解空间中搜索最优解。
核心概念解析:
粒子:算法中的基本搜索单元,包含位置向量和速度向量
位置向量:表示粒子在当前解空间中的坐标(位置可以多维的),对应优化问题的一个候选解
速度向量:决定粒子在解空间中的移动方向和距离
个体最优解(pbest):每个粒子在搜索过程中找到的自身历史最优位置
群体最优解(gbest):整个粒子群迄今为止找到的最优位置
适应度函数:评估解决方案质量的函数,决定解的优劣(在下面的例子中就是求函数的值)
算法步骤详解
1. 初始化阶段
粒子群优化算法开始前需要设置关键参数并初始化粒子群:
参数设置:
粒子数量:粒子越多越离散越好,但粒子越多,计算量就越大
最大迭代次数:控制算法运行时间,也是结束条件之一,迭代次数越多准确性越高,计算量也就越大
惯性权重:平衡全局和局部搜索能力
学习因子:控制个体经验和社会经验的影响程度,包括个体学习因子和群体学习因子
搜索边界:定义解空间的范围限制
粒子初始化:
随机生成每个粒子的初始位置
随机初始化粒子速度
设置个体最优位置为初始位置
计算初始适应度值
确定初始全局最优位置
2. 迭代优化过程
粒子群通过以下步骤进行迭代搜索:
速度更新:
粒子速度由三部分组成:
惯性项:保持粒子原有运动趋势
认知项:引导粒子向自身历史最优位置移动
社会项:引导粒子向群体最优位置移动
速度更新公式:
新速度 = 惯性权重 × 当前速度 + 个体学习因子 × 随机数 × (个体最优位置 - 当前位置) + 群体学习因子 × 随机数 × (群体最优位置 - 当前位置)
位置更新:
粒子根据更新后的速度移动位置(多维的话,每个维度都要计算):
新位置 = 当前位置 + 新速度
边界处理:
当粒子位置超出解空间边界时,采用反弹、吸收或周期性边界策略
对速度进行限制,防止粒子移动过快导致振荡
适应度评估与最优更新:
计算粒子新位置的适应度值
若新适应度优于个体历史最优值,则更新个体最优位置
若新适应度优于群体历史最优值,则更新群体最优位置
3. 终止条件与结果输出
算法在满足以下任一条件时终止:
达到预设的最大迭代次数
群体最优解连续多代无显著改进
找到满足精度要求的最优解
最终输出:
全局最优位置
最优位置对应的最优解
算法简单案例
以下是一个简单的遗传算法实现,用于求解函数 f(x) = x + 10 * sin(5x) + 7 * cos(4x)
的最大值。

//粒子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
算法特性分析
核心优势:
实现简单:算法结构清晰,参数较少
收敛速度快:初期收敛效率高
并行性强:粒子可独立计算,适合并行处理
无需梯度信息:对目标函数要求低
全局搜索能力强:能有效避免局部最优陷阱
局限性:
参数敏感:性能受参数设置影响较大
早熟收敛:可能陷入局部最优
理论分析困难:收敛性证明复杂
离散问题局限:对组合优化问题效果有限
参数选择策略
关键参数:
参数 | 作用 | 推荐范围 | 设置建议 |
---|---|---|---|
粒子数量 | 影响搜索能力 | 20-100 | 问题越复杂,粒子数越多 |
惯性权重 | 平衡全局/局部搜索 | 0.4-0.9 | 采用线性递减策略 |
个体因子(c1) | 控制个体经验影响 | 1.5-2.0 | 与c2保持平衡 |
群体因子(c2) | 控制群体经验影响 | 1.5-2.0 | 大于c1增强全局搜索 |
最大速度 | 限制粒子移动步长 | 解空间范围10%-20% | 防止振荡 |
总结
粒子群优化算法是一种受自然启发的高效优化方法,它通过模拟群体中个体之间的信息共享机制,使整个群体逐渐逼近最优解。虽然其理论基础不如传统数学优化方法严谨,但在实际工程和科研中表现出良好的鲁棒性和实用性。
-END -
如果您关注前端+AI 相关领域可以扫码进群交流
添加小编微信进群😊
关于奇舞团
奇舞团是 360 集团最大的大前端团队,非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。