憋了兩周終于把開題報(bào)告憋出來了,再一次證明自己不適合搞學(xué)術(shù),哎……罢艾,花了點(diǎn)時(shí)間把報(bào)告中提到的粒子群算法看了看,看了些資料嫁乘,用java跑起來昆婿。
算法簡(jiǎn)介
粒子群算法最先由Barnhart博士和Kennedy博士于1995 年提出,是一種源于對(duì)鳥群捕食行為的研究而發(fā)明的進(jìn)化計(jì)算技術(shù)蜓斧,原理是模仿鳥群尋覓食物的搜索過程仓蛆,設(shè)想鳥群在一定區(qū)域搜尋食物,在不知道食物確切位置的情況下挎春,鳥群依靠群體中個(gè)體判斷距離食物的遠(yuǎn)近程度來調(diào)節(jié)飛行方向和飛行速度看疙,最終通過群體的經(jīng)驗(yàn)和自身記憶的智慧找到食物。
算法原理
算法描述
算法流程圖
算法的實(shí)現(xiàn)(java)
- Particle.java文件
package com.jiajia.pso;
import java.util.Random;
/**
* @ClassName: Particle
* @Author: fanjiajia
* @Date: 2019/5/13 上午11:01
* @Version: 1.0
* @Description:
*/
public class Particle {
//維數(shù)
public int dimension = 2;
//粒子的位置
public double[] X = new double[dimension];
//局部最好位置
public double[] pbest = new double[dimension];
//粒子的速度
public double[] V = new double[dimension];
//最大速度
public double Vmax = 2;
//適應(yīng)值
public double fitness;
/**
* 根據(jù)當(dāng)前位置計(jì)算適應(yīng)值
* @return newFitness
*/
public double calculateFitness() {
//1.Ackley's function:
//double newFitness = -20*Math.pow(Math.E,(-0.2*Math.sqrt(0.5*(X[0]*X[0]+X[1]*X[1]))))-Math.pow(Math.E,(0.5*(Math.cos(2*Math.PI*X[0])+Math.cos(2*Math.PI*X[1]))))+Math.E+20;
//2.Sphere function
//double newFitness = X[0]*X[0]+X[1]*X[1];
//3.Rosenbrock function
double newFitness = 100*(Math.pow((X[1]-X[0]*X[0]),2))+Math.pow((X[0]-1), 2);
return newFitness;
}
/**
* 初始化自己的位置和pbest
*/
public void initialX() {
for(int i=0;i<dimension;i++) {
X[i] = new Random().nextInt(50);
pbest[i] = X[i];
}
}
/**
* 初始化自己的速度
*/
public void initialV() {
for(int i=0;i<dimension;i++) {
double tmp = new Random().nextDouble();//隨機(jī)產(chǎn)生一個(gè)0~1的隨機(jī)小數(shù)
V[i] = tmp*4+(-2);
}
}
}
- PSO.java
package com.jiajia.pso;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* @ClassName: PSO
* @Author: fanjiajia
* @Date: 2019/5/13 上午11:02
* @Version: 1.0
* @Description:
*/
public class PSO {
private static double[] gbest;//全局最優(yōu)位置
private static double gbest_fitness = Double.MAX_VALUE;//全局最優(yōu)位置對(duì)應(yīng)的fitness
private static int particle_num = 20;//粒子數(shù)
private static int N = 500;//迭代次數(shù)
private static int c1,c2 = 2;
private static double w = 1.4;//慣性因子
private static List<Particle> particles = new ArrayList<Particle>();//粒子群
private static List<Double> fittessList = new ArrayList<>(N);
/**
* 主程序入口
* @param args
*/
public static void main(String[] args) {
process();
}
/**
* 初始化所有粒子
*/
public static void initialParticles() {
for(int i=0;i<particle_num;i++) {
Particle particle = new Particle();
particle.initialX();
particle.initialV();
particle.fitness = particle.calculateFitness();
particles.add(particle);
}
}
/**
* update gbest
*/
public static void updateGbest() {
double fitness = Double.MAX_VALUE;
int index = 0;
for(int i=0;i<particle_num;i++) { // 找到群體中適應(yīng)值最小的粒子
if(particles.get(i).fitness<fitness) {
index = i;
fitness = particles.get(i).fitness;
}
}
if(fitness<gbest_fitness) { // 如果個(gè)體適應(yīng)值小于全局適應(yīng)值直奋,更新全局的最優(yōu)值為個(gè)體最優(yōu)值
gbest = particles.get(index).pbest.clone();
gbest_fitness = fitness;
}
}
/**
* 跟新每個(gè)粒子的速度
*/
public static void updateV(int n) {
for(Particle particle:particles) {
for(int i=0;i<particle.dimension;i++) {
double v =(0.9 - n*(0.9-0.4)/N) * particle.V[i]+c1*rand()*(particle.pbest[i]-particle.X[i])+c2*rand()*(gbest[i]-particle.X[i]);
if(v>particle.Vmax) // 判斷速度是否超過最大的速度
v = particle.Vmax;
else if(v<-particle.Vmax) // 比最大速度的相反數(shù)小
v = -particle.Vmax;
particle.V[i] = v;//更新Vi
}
}
}
/**
* 更新每個(gè)粒子的位置和pbest
*/
public static void updateX() {
for(Particle particle:particles) {
for(int i=0;i<particle.dimension;i++) {
particle.X[i] = particle.X[i] + particle.V[i];
}
double newFitness = particle.calculateFitness();//新的適應(yīng)值
//如果新的適應(yīng)值比原來的小則跟新fitness和pbest
if(newFitness<particle.fitness) {
particle.pbest = particle.X.clone();
particle.fitness = newFitness;
}
}
}
/**
* 算法主要流程
*/
public static void process() {
int n = 0;
initialParticles();
updateGbest();
while(n++<N) {
updateV(n);
updateX();
updateGbest();
fittessList.add(gbest_fitness);
System.out.println(n+".當(dāng)前gbest:("+gbest[0]+","+gbest[1]+") fitness="+gbest_fitness);
}
write2File();
}
/**
* 返回一個(gè)0~1的隨機(jī)數(shù)
* @return
*/
public static double rand() {
return new Random().nextDouble();
}
}
代碼參考了其他資料能庆,后面有說明,但是對(duì)其中部分進(jìn)行了改進(jìn)脚线。
在Particle
(粒子類)中設(shè)定了三個(gè)適應(yīng)函數(shù)搁胆,Ackley
,Sphere
,Rosenbrock
,關(guān)于這三個(gè)函數(shù)的介紹可以參考資料,這里面列出來了很多優(yōu)化測(cè)試函數(shù)邮绿,很多的paper在設(shè)計(jì)了優(yōu)化策略或者改進(jìn)相應(yīng)的優(yōu)化策略之后渠旁,都會(huì)利用其中的函數(shù)進(jìn)行測(cè)試。
這里用到的函數(shù)是Rosenbrock
:
可以看出這里最小值在(1船逮,1顾腊,,挖胃,1)處取的杂靶。
為了看到相應(yīng)的效果梆惯,這里將全局適應(yīng)值寫到txt文件中,并利用python繪制出來(莫名的感覺繁瑣吗垮,要是python垛吗,哪有這么麻煩,只可惜最后的實(shí)驗(yàn)都是java寫)抱既。
上面是
慣性因子w的優(yōu)化
慣性因子代表受上一次粒子速度的影響程度,
越大寿谴,收斂越快锁右,但容易錯(cuò)過最優(yōu)解。
越小讶泰,收斂較慢咏瑟,容易陷入局部最優(yōu)解,出不來痪署。因此改進(jìn)
成為很多改進(jìn)的焦點(diǎn)码泞,其中采用較多的是Shi建議的線性遞減權(quán)值策略,通常將
設(shè)定在[0.4狼犯,0.9]之間:
采用線性遞減權(quán)值策略后得到的收斂效果:
可以看出前期收斂直線下降余寥,且不容易陷入局部最優(yōu),最后達(dá)到全局收斂悯森。
除了上面的線性遞減權(quán)值策略宋舷,還有自適應(yīng)權(quán)值策略,隨機(jī)權(quán)重策略瓢姻。詳見參考資料[4];
參考資料
- 粒子群算法原理及Matlab實(shí)現(xiàn)
- 基本PSO算法實(shí)現(xiàn)(Java)
- Y.Shi. A Modified Particle Swarm Optimizer. 1998
- Test functions for optimization
- 武裝. 幾種改進(jìn)的智能優(yōu)化算法及其應(yīng)用[M].科學(xué)技術(shù)文獻(xiàn)出版社, 2018.
最后
生命不息祝蝠,生活好難!;眉睢绎狭!