mypro334 发表于 2022-4-23 07:52

【十问十答】粒子群算法(PSO)

1. 粒子群算法基本思想是什么?

粒子群优化算法(Particle swarm optimization, PSO)的基本思想:是通过群体中个体之间的协作和信息共享来寻找最优解。
2. 标准PSO 算法流程是什么?

1)初始化一群微粒(群体规模为N),包括随机位置和速度;
2)评价每个微粒的适应度;
3)对每个微粒,将其适应值与其经过的最好位置pbest作比较,如果较好,则将其作为当前的最好位置pbest;
4)对每个微粒,将其适应值与其经过的最好位置gbest作比较,如果较好,则将其作为当前的最好位置gbest;
5)根据公式(2)、(3)调整微粒速度和位置;
6)未达到结束条件则转第2)步。
迭代终止条件根据具体问题一般选为最大迭代次数Gk或(和)微粒群迄今为止搜索到的最优位置满足预定最小适应阈值


PSO算法过程的形象展示:


3. 采用粒子群优化权值和偏差值的方式训练模型有何优势?

1). 采用粒子群优化方法获取最佳的权值和偏差值,可以提高模型的预测精度。
2). 粒子群优化算法简单易行,可以提高模型的训练速度。
3.) 粒子群优化方法不容易陷入局部极值,原来的权重和偏差值更新方法容易陷入局部极值。
4. 速度和位置更新公式中的参数含义

速度更新公式为:


位置更新公式为:


其中,

[*]i=1,2,···,m。-----表示粒子个数
[*]d=1,2, ···,D. ------表示维数
[*]k------表示当前进化代数,或者说是当前迭代次数
[*]https://www.zhihu.com/equation?tex=x_%7Bid%7D%5E%7Bk%7D -------粒子当前的位置
[*]https://www.zhihu.com/equation?tex=%5Comega ------惯性因子, 为非负值。值较大时,全局寻优能力强,局部寻优能力弱;值较小时,全局寻优能力弱,局部寻优能力强。
计算公式为



https://www.zhihu.com/equation?tex=%5Comega_%7Bini%7D ------为惯性因子初始值,通常设置为0.4

https://www.zhihu.com/equation?tex=%5Comega_%7Bend%7D ------种群迭代到最大进化次数时的惯性因子值,通常设置为0.9

https://www.zhihu.com/equation?tex=k_%7Bmax%7D ------最大迭代次数

[*]https://www.zhihu.com/equation?tex=p_%7Bi%7D ------粒子当前最优位置
[*]https://www.zhihu.com/equation?tex=p_%7Bg%7D ------粒子i对应的全局最优位置
[*]r1和r2------随机初始为0-1之间的数,对群体的多样性有一定的作用
[*]c1和c2------学习因子(也称加速因子),影响算法的收敛速度
5. 参数分析与设置


[*]群体规模N------一般取20~40,对较难或特定类别的问题可以取到100~200。
[*]最大速度Vmax------决定当前位置与最好位置之间的区域的分辨率(或精度)。如果太快,则粒子有可能越过极小点;如果太慢,则粒子不能在局部极小点之外进行足够的探索,会陷入到局部极值区域内。这种限制可以达到防止计算溢出、决定问题空间搜索的粒度的目的。
[*]惯性因子------如果=0,则速度只取决于当前位置和历史最好位置,速度本身没有记忆性。
[*]学习因子c1和c2------c1和c2代表将每个粒子推向pbest和gbest位置的统计加速项的权值。如果令c1=c2=0,粒子将一直以当前速度的飞行,直到边界,很难找到最优解。通常设c1=c2=2。Suganthan的实验表明:c1和c2为常数时可以得到较好的解,但不一定必须等于2。
6. PSO伪代码是什么



7. PSO优缺点是什么

优点:

[*]不依赖于问题信息,算法通用性强。
[*]需要调整的参数少,原理简单,容易实现
[*]协同搜索,同时利用个体局部信息和群体全局信息指导搜索。
[*]收敛速度快, 算法对计算机内存和CPU要求不高
缺点:

[*]算法局部搜索能力较差,搜索精度不够高。
[*]算法不能绝对保证搜索到全局最优解
8. PSO有什么应用


[*]优化神经网络权重
[*]函数优化
[*]模式分类
[*]模糊控制
9. PSO实例1--优化神经网络权重Python

#import tensorflow.compat.v1 as tf
#tf.compat.v1.disable_v2_behavior()
#import tensorflow as tf
#第一次用上面的语句跑的时候还好好的,再跑就报错了
import tensorflow as tf
tf = tf.compat.v1
tf.disable_v2_behavior()


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import random
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPRegressor
from sklearn.preprocessing import StandardScaler


def function(x1,y1,x2,y2,W):#W是神经网络的W权重,根据这个权重设置神经网络


    #定义激活函数
    activation_function=tf.nn.relu
    #输入输出数据集
    xs=tf.placeholder(tf.float32,)
    ys=tf.placeholder(tf.float32,)


    #设计bp神经网络,三层,13,3,1
    weights_1=tf.Variable(W,tf.float32)
    biases_1=tf.Variable(tf.zeros()+0.1,tf.float32)
    wx_plus_b_1=tf.matmul( xs, tf.cast(weights_1,tf.float32))+biases_1
    outputs_1=activation_function(wx_plus_b_1)


    weights_2=tf.Variable(W,tf.float32)
    biases_2=tf.Variable(tf.zeros()+0.1,tf.float32)
    wx_plus_b_2=tf.matmul(outputs_1 , tf.cast(weights_2,tf.float32))+biases_2
    outputs_2=activation_function(wx_plus_b_2)


    w3=W.reshape(3,1)
    weights_3=tf.Variable(w3,tf.float32)
    biases_3=tf.Variable(0.1,tf.float32)

    wx_plus_b_3=tf.matmul(outputs_2,tf.cast(weights_3,tf.float32))+biases_3



    #预测输出结果
    prediction=wx_plus_b_3      #看来这里的数据就用行向量来输入输出

    #定义损失函数
    loss=tf.reduce_mean(tf.reduce_sum(tf.square(y1-prediction),reduction_indices=))

    #梯度下降法训练
    train_step=tf.train.GradientDescentOptimizer(0.1).minimize(loss)

    #初始化变量
    init=tf.global_variables_initializer()

    #执行会话,开始训练模型
    print("开始")
    with tf.Session() as sess:
      sess.run(init)
      for i in range (1000):
            sess.run(train_step,feed_dict={ xs:x1, ys:y1 })

      end_loss=sess.run(loss,feed_dict={xs:x1,ys:y1})
      print(end_loss)
# print(sess.run(prediction,feed_dict={xs:x2}))
      print("结束")
    return end_loss


#导入数据集
data=load_boston()
data_pd=pd.DataFrame(data.data,columns=data.feature_names)
data_pd["price"]=data.target



#dataframe导入numpy
x=np.array(data_pd.loc[:,'CRIM':'LSTAT'])

y=np.array(data_pd.loc[:,'price'])

y.shape=(506,1)
#训练集测试集
x_train,x_test,y_train,y_test=train_test_split(x,y , test_size=0.1 )
#数据标准化
SC=StandardScaler()
x_train=SC.fit_transform(x_train)
y_train=SC.fit_transform(y_train)
x_test=SC.fit_transform(x_test)
y_test=SC.fit_transform(y_test)


#粒子数量num
num = 3

#粒子位置矩阵的形状
num_x = 3
num_y = 13
num_z = 3

#p为粒子位置矩阵,初始化为标准正态分布
p = np.random.randn(num,num_x,num_y,num_z)

#初始化粒子速度,以标准正态分布随机初始化
v = np.random.randn(num,num_x,num_y,num_z)

#个体最佳位置
good_p = np.array(p, copy=True)

#全局最佳位置
best_p = np.zeros((num_x, num_y, num_z))

#每次粒子移动后所计算出新的目标函数值
new_y = np.zeros(num)

#粒子个体历史最优值
good_y = np.zeros(num)

#粒子群体历史最优值
best_y = 0

#计算出初始粒子群的目标函数值
for i in range(num):
    good_y = function(x_train, y_train, x_test, y_test, p)

#目标函数返回值是误差,那么最小的就是最优的
best_y = min(good_y)

#确定初始时最优位置
best_p = p

#设置最大迭代次数
max_iter = 10

#开始迭代
for i in range(max_iter):

    #速度更新公式
    v = random.random() * v + 2.4 * random.random() * (best_p - p) + 1.7 * random.random() * ( good_p - p )

    #粒子位置更新
    p = p + v

    #计算每个粒子到达新位置后所得到的目标函数值
    for i in range(num):
      new_y = function(x_train, y_train, x_test, y_test, p)

    #更新全局最优
    if min(new_y) < best_y:
      best_y = min(new_y)
      best_p = p

    #更新个体历史最优
    for i in range(num):
      if new_y < good_y:
            good_y = new_y
            good_p = p# 当对切片修改时,原始numpy数据也修改


print("结束")
print('目标函数最优值:',best_y)
print('此时的粒子位置:',best_p)
10. PSO实例2--求解函数最值Python

public class AlgorithmPSO {
        int n=2; //粒子个数,这里为了方便演示,我们只取两个,观察其运动方向
    double[] y;
    double[] x;
    double[] v;
    double c1=2;
    double c2=2;
    double pbest[];
    double gbest;
    double vmax=0.1; //速度最大值
    //适应度计算函数,每个粒子都有它的适应度
    public void fitnessFunction(){
      for(int i=0;i<n;i++){
            y=-1*x*(x-2);
      }
    }
    public void init(){ //初始化
      x=new double;
      v=new double;
      y=new double;
      pbest=new double;
      /***
         * 本来是应该随机产生的,为了方便演示,我这里手动随机落两个点,分别落在最大值两边
         */
      x=0.0;
      x=2.0;
      v=0.01;
      v=0.02;
      fitnessFunction();
      //初始化当前个体最优位置,并找到群体最优位置
      for(int i=0;i<n;i++){
            pbest=y;
            if(y>gbest) gbest=y;
      }
      System.out.println("算法开始,起始最优解:"+gbest);
      System.out.print("\n");
    }
    public double getMAX(double a,double b){
      return a>b?a:b;
    }
    //粒子群算法
    public void PSO(int max){
      for(int i=0;i<max;i++){
            double w=0.4;
            for(int j=0;j<n;j++){
                //更新位置和速度,下面就是我们之前重点讲解的两条公式。
                v=w*v+c1*Math.random()*(pbest-x)+c2*Math.random()*(gbest-x);
                if(v>vmax) v=vmax;//控制速度不超过最大值
                x+=v;
               
                //越界判断,范围限定在
                if(x>2) x=2;
                if(x<0) x=0;
               
            }
            fitnessFunction();
            //更新个体极值和群体极值
            for(int j=0;j<n;j++){
                pbest=getMAX(y,pbest);
                if(pbest>gbest) gbest=pbest;
                System.out.println("粒子n"+j+": x = "+x+""+"v = "+v);
            }
            System.out.println("第"+(i+1)+"次迭代,全局最优解 gbest = "+gbest);
            System.out.print("\n");
      }
      
    }
    //运行我们的算法
    public static void main(String[] args){
            AlgorithmPSO ts=new AlgorithmPSO();
      ts.init();
      ts.PSO(10);//为了方便演示,我们暂时迭代10次。
    }

}输出结果:
算法开始,起始最优解:0.0

粒子n0: x = 0.004v = 0.004
粒子n1: x = 0.0v = -4.065770842472382
第1次迭代,全局最优解 gbest = 0.007984

粒子n0: x = 0.01778510589090629v = 0.013785105890906289
粒子n1: x = 0.0v = -1.625639647649872
第2次迭代,全局最优解 gbest = 0.03525390179026183

粒子n0: x = 0.0610276658084214v = 0.04324255991751511
粒子n1: x = 0.0v = -0.6035255880722042
第3次迭代,全局最优解 gbest = 0.11833095562281844

粒子n0: x = 0.1610276658084214v = 0.1
粒子n1: x = 0.0v = -0.012719944703824898
第4次迭代,全局最优解 gbest = 0.29612542246113416

粒子n0: x = 0.2610276658084214v = 0.1
粒子n1: x = 0.06231495466940402v = 0.06231495466940402
第5次迭代,全局最优解 gbest = 0.4539198892994499

粒子n0: x = 0.3610276658084214v = 0.1
粒子n1: x = 0.16231495466940402v = 0.1
第6次迭代,全局最优解 gbest = 0.5917143561377656

粒子n0: x = 0.46102766580842136v = 0.1
粒子n1: x = 0.262314954669404v = 0.1
第7次迭代,全局最优解 gbest = 0.7095088229760813

粒子n0: x = 0.5610276658084213v = 0.1
粒子n1: x = 0.362314954669404v = 0.1
第8次迭代,全局最优解 gbest = 0.8073032898143969

粒子n0: x = 0.6610276658084213v = 0.1
粒子n1: x = 0.462314954669404v = 0.1
第9次迭代,全局最优解 gbest = 0.8850977566527127

粒子n0: x = 0.7610276658084213v = 0.1
粒子n1: x = 0.562314954669404v = 0.1
第10次迭代,全局最优解 gbest = 0.9428922234910285现在我们来观察两个粒子的位移x在每一次迭代中的变化(离食物的距离)。
1) 初始状态
粒子n0: x = 0.0 v = 0.01
粒子n1: x = 2.0 v = 0.02


两个粒子位于区间两端。
2) 第一次迭代
粒子n0: x = 0.004 v = 0.004
粒子n1: x = 0.0 v = -4.065770842472382


两个粒子都跑到原点了。
3) 第二、三……十次迭代


可以看到,两个粒子在不断靠近最优点。上面多个圈是他们聚集的过程,可以看出来,聚集过程是个越来越密集的过程。这才是10次迭代而已。如果我们加大迭代次数,很容易就找出最优解了。最后放上一个迭代100次的结果:


<hr/>参考资料:
【算法】粒子群算法Particle Swarm Optimization超详细解析+代码实例讲解 - 云+社区 - 腾讯云 (tencent.com) 粒子群优化BP神经网络初始权值(python实现)_哈哈傻的博客-CSDN博客_粒子群优化bp神经网络
经典优化算法 | 粒子群算法解析 - 知乎 (zhihu.com)
————————————————
原文链接:【十问十答】粒子群算法(PSO)_allein_STR的博客-CSDN博客
页: [1]
查看完整版本: 【十问十答】粒子群算法(PSO)