粒子群算法(PSO)的Python实现(求解多元函数的极值)

粒子群算法(PSO)的Python实现(求解多元函数的极值)PSO是寻优算法中比较简单的一种,本文用Python简单实现了PSO算法,用来求解一个五元函数的最大值,并与MATLAB的fmincon函数的运行结果做比较。

大家好,又见面了,我是你们的朋友全栈君。

PSO算法算是寻优算法中比较简单的一种,其大概思想是:
在这里插入图片描述
现在我们计算:
在这里插入图片描述
的极大值,每一个变量的取值范围都是(1,25)。
Python代码为:

# -*- coding: utf-8 -*-
""" @Time : 2020/9/13 10:08 @Author :KI @File :pso.py @Motto:Hungry And Humble """
import math
import random
import numpy as np
import matplotlib.pyplot as plt
import pylab as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']


class PSO:
    def __init__(self, dimension, time, size, low, up, v_low, v_high):
        # 初始化
        self.dimension = dimension  # 变量个数
        self.time = time  # 迭代的代数
        self.size = size  # 种群大小
        self.bound = []  # 变量的约束范围
        self.bound.append(low)
        self.bound.append(up)
        self.v_low = v_low
        self.v_high = v_high
        self.x = np.zeros((self.size, self.dimension))  # 所有粒子的位置
        self.v = np.zeros((self.size, self.dimension))  # 所有粒子的速度
        self.p_best = np.zeros((self.size, self.dimension))  # 每个粒子最优的位置
        self.g_best = np.zeros((1, self.dimension))[0]  # 全局最优的位置

        # 初始化第0代初始全局最优解
        temp = -1000000
        for i in range(self.size):
            for j in range(self.dimension):
                self.x[i][j] = random.uniform(self.bound[0][j], self.bound[1][j])
                self.v[i][j] = random.uniform(self.v_low, self.v_high)
            self.p_best[i] = self.x[i]  # 储存最优的个体
            fit = self.fitness(self.p_best[i])
            # 做出修改
            if fit > temp:
                self.g_best = self.p_best[i]
                temp = fit

    def fitness(self, x):
        """ 个体适应值计算 """
        x1 = x[0]
        x2 = x[1]
        x3 = x[2]
        x4 = x[3]
        x5 = x[4]
        y = math.floor((x2 * np.exp(x1) + x3 * np.sin(x2) + x4 + x5) * 100) / 100
        # print(y)
        return y

    def update(self, size):
        c1 = 2.0  # 学习因子
        c2 = 2.0
        w = 0.8  # 自身权重因子
        for i in range(size):
            # 更新速度(核心公式)
            self.v[i] = w * self.v[i] + c1 * random.uniform(0, 1) * (
                    self.p_best[i] - self.x[i]) + c2 * random.uniform(0, 1) * (self.g_best - self.x[i])
            # 速度限制
            for j in range(self.dimension):
                if self.v[i][j] < self.v_low:
                    self.v[i][j] = self.v_low
                if self.v[i][j] > self.v_high:
                    self.v[i][j] = self.v_high

            # 更新位置
            self.x[i] = self.x[i] + self.v[i]
            # 位置限制
            for j in range(self.dimension):
                if self.x[i][j] < self.bound[0][j]:
                    self.x[i][j] = self.bound[0][j]
                if self.x[i][j] > self.bound[1][j]:
                    self.x[i][j] = self.bound[1][j]
            # 更新p_best和g_best
            if self.fitness(self.x[i]) > self.fitness(self.p_best[i]):
                self.p_best[i] = self.x[i]
            if self.fitness(self.x[i]) > self.fitness(self.g_best):
                self.g_best = self.x[i]

    def pso(self):
        best = []
        self.final_best = np.array([1, 2, 3, 4, 5])
        for gen in range(self.time):
            self.update(self.size)
            if self.fitness(self.g_best) > self.fitness(self.final_best):
                self.final_best = self.g_best.copy()
            print('当前最佳位置:{}'.format(self.final_best))
            temp = self.fitness(self.final_best)
            print('当前的最佳适应度:{}'.format(temp))
            best.append(temp)
        t = [i for i in range(self.time)]
        plt.figure()
        plt.plot(t, best, color='red', marker='.', ms=15)
        plt.rcParams['axes.unicode_minus'] = False
        plt.margins(0)
        plt.xlabel(u"迭代次数")  # X轴标签
        plt.ylabel(u"适应度")  # Y轴标签
        plt.title(u"迭代过程")  # 标题
        plt.show()


if __name__ == '__main__':
    time = 50
    size = 100
    dimension = 5
    v_low = -1
    v_high = 1
    low = [1, 1, 1, 1, 1]
    up = [25, 25, 25, 25, 25]
    pso = PSO(dimension, time, size, low, up, v_low, v_high)
    pso.pso()

运行结果:
在这里插入图片描述
收敛过程:
在这里插入图片描述
可以看出,不到10次就收敛了。

matlab代码:

z=@(x)-(x(2)*exp(x(1))+x(3)*sin(x(2))+x(4)*x(5));
x0=[1;1;1;1;1];
[x,feval]=fmincon(z,x0,[],[],[],[],[1;1;1;1;1],[25;25;25;25;25])

运行结果:

x =

   25.0000
   25.0000
   13.1400
    1.0002
    1.0002


feval =
  -1.8001e+12

如果想要利用上述代码求极小值,可以有以下两种办法:

  1. 将fitness函数中的返回值改为-y,此时如果求出的值为z,那么函数的极小值就为-z。
  2. 将第34行代码处的temp改为一个很大的值;将第42、83、85以及93行代码处的”>“改为”<“。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/130988.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 学习opencv之cvtColor

    opencv提供了cvtColor()函数,用于在图像中不同的色彩空间进行转换,用于后续处理。在使用cvtColor之前首先需要了解下基本的图像色彩模式,色彩模式决定了打印或显示的图片颜色。图像色彩模式位图模式位图模式是图像中最基本的格式,图像只有黑色和白色像素,是色彩模式中占有空间最小的,同样也叫做黑白图,它包含的信息量最少,无法包含图像中的细节,相当于只有0或者1一副彩色图如…

    2022年4月18日
    44
  • String 转 JSONArray 日常挖坑填坑

    String 转 JSONArray 日常挖坑填坑1.lists里面的Map中的key不为list时均正常   List&lt;Map&lt;String,String&gt;&gt;lists=null;   if(cmtMaps.containsKey("cmtComments")){      lists=JSONArray.parseObject(cmtMaps.get("cmtComments"),Li…

    2022年6月20日
    80
  • 神经网络 – BP神经网络与RBF神经网络模型解决实际问题 – (Matlab建模)

    神经网络 – BP神经网络与RBF神经网络模型解决实际问题 – (Matlab建模)目录神经网络模型简述实例:交通运输能力预测设计MATLAB程序及仿真结果由于货物运输、地方经济及企业发展的紧密联系,因此作为反映货物运输需求的一项重要指标,货运量预测研究和分析具有较强的实际意义。常用的货运量预测方法包括时间序列方法、移动平滑法、指数平滑和随机时间序列方法、相关(回归)分析法、灰色预测方法和作为多种方法综合的组合预测方法等.这些方法大都集中在对…

    2025年7月2日
    4
  • kinect深度距离误差_TOF相机深度矫正基于Kinect v2

    kinect深度距离误差_TOF相机深度矫正基于Kinect v2之前的文章《answer:深度相机(TOF)矫正》由于时间匆忙,临时想了一种深度相机深度像素矫正方法,即固定高度逐像素矫正。该方法简单粗暴,效果并不理想,最近查阅了相关文献资料,基于之前的思路整理出一种现场可用的简单易行的矫正方法。二维平面畸变矫正使用张氏标定法对二维平面进行径向畸变矫正。深度像素矫正做图像处理的难点在于图像包括图像的噪声随机性很大,即使在同一位置拍摄也没有完全一样的图像,所以所设…

    2022年5月25日
    38
  • js删除数组中指定元素或者空字符串

    js删除数组中指定元素或者空字符串

    2021年11月22日
    61
  • pycharm添加anaconda解释器_anaconda找不到指定模块

    pycharm添加anaconda解释器_anaconda找不到指定模块Pycharmanaconda创建虚拟环境章节导航Pycharmanaconda创建虚拟环境背景知识Pycharm新建环境Pycharm使用已创建环境实操方案创建新项目选择已存在解释器在Pycharm添加已存在的解释器进入该项目的解释器设置页面查看解释器所带软件包背景知识Pycharm新建环境PyCharm使用anaconda新建环境是只包含一些基础包,后续如果想要如Scrapy.requests等库的话则需要自己在解释器页面添加了(ctrl+alt+s进入解释器设置页面)而且新环境中的

    2022年8月29日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号