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

内容

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

2. 标准PSO 算法流程是什么?

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

4. 速度和位置更新公式中的参数含义

5. 参数分析与设置

6. PSO伪代码是什么

7. PSO优缺点是什么

8. PSO有什么应用

9. PSO实例1–优化神经网络权重Python

10. PSO实例2–求解函数最值Python

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

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

2. 标准PSO 算法流程是什么?

1)初始化一群微粒(群体规模为N),包括随机位置和速度;
2)评价每个微粒的适应度;
3)对每个微粒,将其适应值与其经过的最好位置pbest作比较,如果较好,则将其作为当前的最好位置pbest;
4)对每个微粒,将其适应值与其经过的最好位置gbest作比较,如果较好,则将其作为当前的最好位置gbest;
5)根据公式(2)、(3)调整微粒速度和位置;
6)未达到结束条件则转第2)步。

迭代终止条件根据具体问题一般选为最大迭代次数Gk或(和)微粒群迄今为止搜索到的最优位置满足预定最小适应阈值

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

PSO算法过程的形象展示:

这里写图片描述

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

1). 采用粒子群优化方法获取最佳的权值和偏差值,可以提高模型的预测精度。

2). 粒子群优化算法简单易行,可以提高模型的训练速度。

3.) 粒子群优化方法不容易陷入局部极值,原来的权重和偏差值更新方法容易陷入局部极值。

4. 速度和位置更新公式中的参数含义

速度更新公式为:

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

位置更新公式为:

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

在,

  • i=1,2,···,m。—–表示粒子个数
  • d=1,2, ···,D. ——表示维数
  • k——表示当前进化代数,或者说是当前迭代次数
  • x_{id}^{k}——粒子的当前位置
  • \omega——惯性系数,为非负值。值大时,全局优化能力强,局部优化能力弱;值小时,全局优化能力弱,局部优化能力强。

计算公式为

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

\omega_{ini}——为惯性因子初始值,通常设置为0.4

\omega_{end}——种群迭代到最大进化次数时的惯性因子值,通常设置为0.9

k_{max}——–最大迭代次数

  • p_{i}——粒子当前最优位置
  • p_{g}——粒子i对应的全局最优位置
  • r1和r2——随机初始为0-1之间的数,对群体的多样性有一定的作用
  • c1和c2——学习因子(也称加速因子),影响算法的收敛速度

5. 参数分析与设置

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

6. PSO伪代码是什么

【十问十答】粒子群算法(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,[None,None])
    ys=tf.placeholder(tf.float32,[None,None])


    #设计bp神经网络,三层,13,3,1
    weights_1=tf.Variable(W[0,:,:],tf.float32)
    biases_1=tf.Variable(tf.zeros([1,3])+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[1,0:3,:],tf.float32)
    biases_2=tf.Variable(tf.zeros([1,3])+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[2,0:3,0].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=[1]))

    #梯度下降法训练
    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[i] = function(x_train, y_train, x_test, y_test, p[i, :, :, :])

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

#确定初始时最优位置
best_p = p[np.argmin(good_y), :, :, :]

#设置最大迭代次数
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[i] = function(x_train, y_train, x_test, y_test, p[i, :, :, :])

    #更新全局最优
    if min(new_y) < best_y:
        best_y = min(new_y)
        best_p = p[np.argmin(new_y), :, :, :]

    #更新个体历史最优
    for i in range(num):
        if new_y[i] < good_y[i]:
            good_y[i] = new_y[i]
            good_p[i, :, :, :] = p[i, :, :, :]  # 当对切片修改时,原始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[i]=-1*x[i]*(x[i]-2);
        }
    }
    public void init(){ //初始化
        x=new double[n];
        v=new double[n];
        y=new double[n];
        pbest=new double[n];
        /***
         * 本来是应该随机产生的,为了方便演示,我这里手动随机落两个点,分别落在最大值两边
         */
        x[0]=0.0;
        x[1]=2.0;
        v[0]=0.01;
        v[1]=0.02;
        fitnessFunction();
        //初始化当前个体最优位置,并找到群体最优位置
        for(int i=0;i<n;i++){
            pbest[i]=y[i];
            if(y[i]>gbest) gbest=y[i];
        }
        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[j]=w*v[j]+c1*Math.random()*(pbest[j]-x[j])+c2*Math.random()*(gbest-x[j]);
                if(v[j]>vmax) v[j]=vmax;//控制速度不超过最大值
                x[j]+=v[j];
                
                //越界判断,范围限定在[0, 2]
                if(x[j]>2) x[j]=2;
                if(x[j]<0) x[j]=0;
                
            }
            fitnessFunction();
            //更新个体极值和群体极值
            for(int j=0;j<n;j++){
                pbest[j]=getMAX(y[j],pbest[j]);
                if(pbest[j]>gbest) gbest=pbest[j];
                System.out.println("粒子n"+j+": x = "+x[j]+"  "+"v = "+v[j]);
            }
            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.004  v = 0.004
粒子n1: x = 0.0  v = -4.065770842472382
第1次迭代,全局最优解 gbest = 0.007984

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

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

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

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

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

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

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

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

粒子n0: x = 0.7610276658084213  v = 0.1
粒子n1: x = 0.562314954669404  v = 0.1
第10次迭代,全局最优解 gbest = 0.9428922234910285

现在我们来观察两个粒子的位移x在每一次迭代中的变化(离食物的距离)。

1) 初始状态

粒子n0: x = 0.0 v = 0.01

粒子n1: x = 2.0 v = 0.02

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

两个粒子位于区间的两端。

2) 第一次迭代

粒子n0: x = 0.004 v = 0.004

粒子n1: x = 0.0 v = -4.065770842472382

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

两个粒子都跑到了原点。

3) 第二、三……十次迭代

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

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

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

参考:

【算法】粒子群算法Particle Swarm Optimization超详细解析+代码实例讲解 – 云+社区 – 腾讯云 (tencent.com)粒子群优化BP神经网络初始权值(python实现)_哈哈傻的博客-CSDN博客_粒子群优化bp神经网络

经典优化算法 | 粒子群算法解析 – 知乎 (zhihu.com)

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2022年4月10日 下午4:43
下一篇 2022年4月10日 下午5:01

相关推荐