粒子群算法(PSO)的python实现


前言

CSDN上找了一圈粒子群算法的python代码,全是以类来写的,由于对类不感冒(其实是不咋会用),于是参照matlab版本的代码写了一个纯函数调用不带类的版本,并不复杂,没必要使用。

一、粒子群算法的原理

原理部分别的博客已经介绍得很清楚了,就不再介绍了,放个链接:https://blog.csdn.net/daaikuaichuan/article/details/81382794这个讲的比较直白易懂了。
在这里插入图片描述
在这里插入图片描述

二、python代码实现

参考:粒子群算法的matlab实现
首先放一些参数的意义和常见的取值范围:
在这里插入图片描述
对照matlab代码,用python实现如下。我这里是将训练好的神经网络模型当成适应度函数,并给它加上了惩罚度,如何调用神经网络模型利用遗传算法寻优感兴趣的可以看看我的另一篇文章:利用深度学习模型基于遗传算法(GA)寻求最优解,迁移到其他问题将适应度函数def F(x):替换成你需要求解的就可以了。

'''
autor: wsw
Time: 2021.8.28
'''
from tensorflow_core import keras
import numpy as np
from tensorflow.keras.models import load_model
import os
import matplotlib.pyplot as plt
import random

SIZE = 100  #初始化种群数量,初始种群取50-1000都是可以的,虽然初始种群越大收敛性会更好,不过太大了也会影响速度
DIM = 1 #空间维数,自变量的个数
N = 100  #迭代次数,一般取100~4000,太少解不稳定,太多浪费时间
x_limit = [0.2, 1]   #位置参数限制   变量x的取值范围   燃料极水的摩尔分数
v_limit = [-0.1, 0.1]  #速度限制  一般设为每维变量变化范围的10%~20%  如果粒子飞行速度过快,很可能直接飞过最优解位置,但是如果飞行速度过慢,会使得收敛速度变慢
w = 0.8   #惯性权重  该参数反映了个体历史成绩对现在的影响,一般取0.5~1;
c1 = 0.5   #自我学习因子,一般取0~4,此处要根据自变量的取值范围来定,并且学习因子分为个体和群体两种
c2 = 0.5   #群体学习因子

'''输入固定参数'''
V = 1.4
I = 24000
T = 1083
V_BOUND = [0.7, 1.8]
I_BOUND = [4.39, 30309.58]
T_BOUND = [1023, 1123]
Q_BOUND = [-1.4588, 9.4078]
'''将输入参数按照训练模型时采用的归一化方法归一化'''
nor_V = 0.8 * (V - 0.7) / (1.8 - 0.7) + 0.2
nor_I = 0.8 * (I - 4.39) / (30309.58 - 4.39) + 0.2
nor_T = 0.8 * (T - 1023) / (1123 - 1023) + 0.2


def rmse(y_true, y_pred):  #模型中自定义的评价函数,加载模型时需要加上
    return keras.backend.sqrt(keras.backend.mean(keras.backend.square(y_pred - y_true), axis=-1))

folder = "D:\Desktop\模型文件"  #模型所在位置
os.chdir(folder)
global model
global Q_MIN_EPOCH
global xH2O

model = load_model('D:\Desktop\AI+遗传算法\由xH2O预测SCCM\checkpoint6_830_12点19\model.h5',custom_objects={'rmse': rmse})

'''适应度函数,将所有种群输入模型得到预测值'''
def F(x):
    num = x.shape[0]
    X2 = []
    T = False
    SCCM_max = 4   #非热中性点和非最低热值点可以取的最大值(归一化后)
    Q_real_min = 10  #热量真实值最小值初值
    Q_real_max = 0  #热量真实值最大值初值
    for i in range(num):   #将种群参数加上固定参数组成训练模型的输入
        X = [nor_V, nor_I, nor_T, x[i, 0]]
        X2.append(X)
    Xtest = np.array(X2)
    X_test = Xtest.reshape(-1, 4)
    Y_pre = model.predict(X_test)

    for i in range(num):  #遍历,判断能否达到热中性
        if Y_pre[i, 0] > 3.8 or Y_pre[i, 0] < 0:  # 当预测值出现偏差超出最大流量限制,或比最小流量小时,跳出循环
                print("\n参数选择异常,SCCM>1200或SCCM<300,请重新选择合理参数\n")
                exit()
        Q_real = (Y_pre[i, -1] - 0.2) / 0.8 * (9.4078 + 1.4588) - 1.4588  # 将输出参数由归一化值转为实际值

        # if Y_pre[i, 0] < SCCM_min:  #流量的最小值(归一化后)   最小值可能比能达到的最大值SCCM_MAX大  所以不如取0
        #     SCCM_min = Y_pre[i, 0]

        if abs(Q_real) < 1e-7:
            T = True
            if Y_pre[i, 0] < SCCM_max:
                SCCM_max = 0.7 * Y_pre[i, 0]   #如果能达到热中性,所有热中性点中的最小SCCM为非热中性点可以达到的最大值,非热中性点适应度应当更小,加上惩罚数
        if abs(Q_real) > Q_real_max:
            Q_real_max = abs(Q_real)   #得到该条件下热量真实值最大值

    i_last = 0
    if T == False:   #如果达不到热中性计算热量最小值
        for i in range(num):
            Q_real = (Y_pre[i, -1] - 0.2) / 0.8 * (9.4078 + 1.4588) - 1.4588  # 将输出参数由归一化值转为实际值
            if abs(Q_real) < Q_real_min:
                Q_real_min = abs(Q_real)
                i_last = i
                SCCM_max = 0.7 * Y_pre[i, 0] #最小放热量对应的流量,应成为其他点可以达到的最大适应度

    # if SCCM_max < 0:  #防止非热中性点的流量归一化值在加上惩罚数以后小于最小0
    #     SCCM_max = 0.0000001

    for i in range(num):    #限制条件:热中性,同时排除个别误差值较大的数据的影响
        Q_real = (Y_pre[i, -1] - 0.2) / 0.8 * (9.4078 + 1.4588) - 1.4588  # 将输出参数由归一化值转为实际值
        if abs(Q_real) > 1e-7:
            if abs(Q_real) > Q_real_min:
                Y_TEMP = 1e-7 + (Q_real_max - abs(Q_real))/(Q_real_max-Q_real_min)*SCCM_max  #惩罚函数,无法达到热中性时减小适应度,离最低Q越近适应度越大,不能超过SCCM_max
                if Y_TEMP < Y_pre[i, 0]:   #加上惩罚函数的适应度小于原适应度,替换原适应度
                    Y_pre[i, 0] = Y_TEMP

    Q_MIN_EPOCH.append(Q_real_min)
    xH2O.append(Xtest[i_last, 3])

    return Y_pre[:, 0]   #返回燃料极流量归一化值

'''计算适应度'''
def get_fitness(PSO):
    pred = F(PSO)
    return pred  #返回由深度学习模型预测的SCCM归一化值

if __name__ == "__main__":
    PSO = np.random.uniform(x_limit[0], x_limit[1], (1, DIM)) #粒子位置初始化
    VEL = np.random.uniform(v_limit[0], v_limit[1], (1, DIM)) #粒子速度初始化
    max_fit_record = []  #记录最大值
    Q_MIN_EPOCH = []  #记录最小热量
    xH2O = []  #记录对应的水的摩尔分数

    for i in range(SIZE - 1):
        pso = np.random.uniform(x_limit[0], x_limit[1], (1, DIM))
        PSO = np.concatenate((PSO, pso), axis=0)
        vel = np.random.uniform(v_limit[0], v_limit[1], (1, DIM))
        VEL = np.concatenate((VEL, vel), axis=0)
    x_max = PSO  #每个个体的历史最佳位置
    y_max = np.zeros(DIM)  #种群的历史最佳位置
    fxm = np.zeros((SIZE, 1)) #每个个体的历史最佳适应度
    fym = 0 #种群历史最佳适应度

    #群体更新
    for i in range(N):
        fx = get_fitness(PSO)   #个体适应度
        for j in range(SIZE):
            if fxm[i] < fx[i]:  #更新个体历史最佳适应度
                fxm[i] = fx[i]  #更新个体历史最佳位置
                x_max[i, :] = PSO[i, :]
        if fym < np.max(fxm):
            fym = np.max(fxm)
            nmax = np.argmax(fxm)  #更新群体历史最佳适应度
            y_max = x_max[nmax, :]  #更新群体历史最佳位置

        VEL = VEL * w + c1 * random.random() * (x_max - PSO) + c2 * random.random() * (np.tile(y_max, (SIZE, 1)) - PSO)  #速度更新

        VEL[VEL > v_limit[1]] = v_limit[1]   #边界速度处理
        VEL[VEL < v_limit[0]] = v_limit[0]

        PSO[PSO > x_limit[1]] = x_limit[1]
        PSO[PSO > x_limit[0]] = x_limit[0]

        max_fit_record.append(fym)

    xH2O_real = (xH2O[-1] - 0.2) / 0.8 * (0.9 - 0.1) + 0.1
    SCCM_max = (fym - 0.2) / 0.8 * (550 - 350) + 350
    #输出最优解
    print('最大流量SCCM:', SCCM_max)
    print('此时水的摩尔分数:', xH2O_real)
    print('此时最小热量Q_min:', Q_MIN_EPOCH[-1])

    fig = plt.figure()
    plt.subplot(221)
    plt.plot(max_fit_record, label='generation')
    plt.legend()  # 用于给图像加图例。
    plt.xlabel('epoch')
    plt.ylabel('max_fitness')

    plt.subplot(222)
    plt.plot(Q_MIN_EPOCH, label='Q_real_min')
    plt.legend()  # 用于给图像加图例。
    plt.xlabel('epoch')
    plt.ylabel('Q_real_min')

    plt.subplot(223)
    plt.plot(xH2O, label='xH2O')
    plt.legend()  # 用于给图像加图例。
    plt.xlabel('epoch')
    plt.ylabel('xH2O')
    plt.show()

总结

粒子群算法的实现思路比较简单,不需要编码、交叉、变异,相对遗传算法代码量会更少,不涉及惩罚函数、神经网络模型直接看主函数部分就好。

if __name__ == "__main__":
    PSO = np.random.uniform(x_limit[0], x_limit[1], (1, DIM)) #粒子位置初始化
    VEL = np.random.uniform(v_limit[0], v_limit[1], (1, DIM)) #粒子速度初始化
    max_fit_record = []  #记录最大值
    Q_MIN_EPOCH = []  #记录最小热量
    xH2O = []  #记录对应的水的摩尔分数

    for i in range(SIZE - 1):
        pso = np.random.uniform(x_limit[0], x_limit[1], (1, DIM))
        PSO = np.concatenate((PSO, pso), axis=0)
        vel = np.random.uniform(v_limit[0], v_limit[1], (1, DIM))
        VEL = np.concatenate((VEL, vel), axis=0)
    x_max = PSO  #每个个体的历史最佳位置
    y_max = np.zeros(DIM)  #种群的历史最佳位置
    fxm = np.zeros((SIZE, 1)) #每个个体的历史最佳适应度
    fym = 0 #种群历史最佳适应度

    #群体更新
    for i in range(N):
        fx = get_fitness(PSO)   #个体适应度
        for j in range(SIZE):
            if fxm[i] < fx[i]:  #更新个体历史最佳适应度
                fxm[i] = fx[i]  #更新个体历史最佳位置
                x_max[i, :] = PSO[i, :]
        if fym < np.max(fxm):
            fym = np.max(fxm)
            nmax = np.argmax(fxm)  #更新群体历史最佳适应度
            y_max = x_max[nmax, :]  #更新群体历史最佳位置

        VEL = VEL * w + c1 * random.random() * (x_max - PSO) + c2 * random.random() * (np.tile(y_max, (SIZE, 1)) - PSO)  #速度更新

        VEL[VEL > v_limit[1]] = v_limit[1]   #边界速度处理
        VEL[VEL < v_limit[0]] = v_limit[0]

        PSO[PSO > x_limit[1]] = x_limit[1]
        PSO[PSO > x_limit[0]] = x_limit[0]

        max_fit_record.append(fym)
    #输出最优解
    print('适应度:', fym)


  • 2
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
粒子群算法(Particle Swarm Optimization,PSO)是一种优化算法,灵感来自于鸟群觅食的行为。它是一种通过模拟个体间的协作与信息共享来搜索最优解的算法。 Long Short-Term Memory(LSTM)是一种常用于处理时间序列数据的深度学习模型。它具有记忆性和遗忘机制,能够有效地捕捉到长期依赖的特征。 将PSO与LSTM结合,可以用于训练LSTM模型的参数优化。在使用PSO优化LSTM模型的参数时,可以将每个粒子看作LSTM模型的一个参数组合,通过不断迭代和搜索来寻找最优的参数组合,以获得更好的LSTM模型效果。 首先,通过定义粒子的位置和速度,设置LSTM模型的参数空间范围。然后根据某个评价指标(如损失函数)对每个粒子进行评估,并更新粒子的速度和位置。 接着,在每次迭代中,根据粒子的速度和位置,更新LSTM模型的参数。通过不断迭代和更新,粒子群算法可以在参数空间中搜索到最优的参数组合,从而优化LSTM模型的性能。 使用Python实现PSO-LSTM算法时,可以借助第三方库如pyswarms来实现PSO算法,使用Keras或TensorFlow来构建和训练LSTM模型。 总之,粒子群算法PSO可以用于优化LSTM模型的参数,通过迭代和搜索的方式寻找最优的参数组合,以提升LSTM模型在时间序列数据上的表现。这种方法在处理时间序列预测、文本生成等问题上具有广泛的应用前景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值