用 Python 实现粒子群算法

作者简介:Boblee,人工智能硕士毕业,擅长及爱好Python,基于Python研究人工智能、群体智能、区块链等技术,并使用Python开发前后端、爬虫等。

一、粒子群算法介绍

1、初始化

首先,我们设置最大迭代次数,目标函数的自变量个数,粒子的最大速度,位置信息为整个搜索空间,我们在速度区间和搜索空间上随机初始化速度和位置,设置粒子群规模为M,每个粒子随机初始化一个飞翔速度。

2、个体极值与全局最优解

定义适应度函数,个体极值为每个粒子找到的最优解,从这些最优解找到一个全局值,叫做本次全局最优解。与历史全局最优比较,进行更新。

3、更新速度和位置的公式

节选自 https://blog.csdn.net/weixin_40679412/article/details/80571854

二、算法实现

1、初始化粒子,计算适应度值

初始化粒子x及速度v,并调用适应度函数计算适应度值。并选出最小适应度值及对应的x值。

x = []
v = []
for j in range(self.N):
    x.append([random.random() for i in range(self.dim)])
    v.append([random.random() for m in range(self.dim)])
fitness = [self.fun(x[j]) for j in range(self.N)]
p = x
best = min(fitness)
pg = x[fitness.index(min(fitness))]

2、更新粒子位置,计算新适应度值

根据1中公式更新粒子位置及速度,并调用适应度函数计算适应度值。

for t in range(self.T):
    for j in range(self.N):
        for m in range(self.dim):
            v[j][m] = self.w * v[j][m] + self.c1 * random.random() * (
                    p[j][m] - x[j][m]) + self.c2 * random.random() * (pg[m] - x[j][m])
    for j in range(self.N):
        for m in range(self.dim):
            x[j][m] = x[j][m] + v[j][m]
            if x[j][m] > self.x_bound[1]:
                x[j][m] = self.x_bound[1]
            if x[j][m] < self.x_bound[0]:
                x[j][m] = self.x_bound[0]
    fitness_ = []
    for j in range(self.N):
        fitness_.append(self.fun(x[j]))

3、更新粒子全局最优解

如果新计算出的适应度值比前期计算的适应度值小,则更新粒子全局最优解。

if min(fitness_) < best:
    pg = x[fitness_.index(min(fitness_))]
    best = min(fitness_)

4、整体代码

其中T为迭代次数,x_bound为粒子范围,wc1c2为公式参数,dim为粒子维度,N为每次迭代粒子总数。fun函数根据需要自己修改。

import random
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 步骤一(替换sans-serif字体)
plt.rcParams['axes.unicode_minus'] = False


class PSO(object):
    def __init__(self):
        self.x_bound = [-1, 1]
        self.T = 100
        self.w = 0.15
        self.N = 10000
        self.dim = 20
        self.c1 = 1.5
        self.c2 = 1.5

    def fun(self, x):
        result = 0
        for i in x:
            result = result + pow(i, 2)
        return result

    def pso_main(self):
        x = []
        v = []
        for j in range(self.N):
            x.append([random.random() for i in range(self.dim)])
            v.append([random.random() for m in range(self.dim)])
        fitness = [self.fun(x[j]) for j in range(self.N)]
        p = x
        best = min(fitness)
        pg = x[fitness.index(min(fitness))]
        best_all = []
        for t in range(self.T):
            for j in range(self.N):
                for m in range(self.dim):
                    v[j][m] = self.w * v[j][m] + self.c1 * random.random() * (
                            p[j][m] - x[j][m]) + self.c2 * random.random() * (pg[m] - x[j][m])
            for j in range(self.N):
                for m in range(self.dim):
                    x[j][m] = x[j][m] + v[j][m]
                    if x[j][m] > self.x_bound[1]:
                        x[j][m] = self.x_bound[1]
                    if x[j][m] < self.x_bound[0]:
                        x[j][m] = self.x_bound[0]
            fitness_ = []
            for j in range(self.N):
                fitness_.append(self.fun(x[j]))
            if min(fitness_) < best:
                pg = x[fitness_.index(min(fitness_))]
                best = min(fitness_)
            best_all.append(best)
            print('第' + str(t) + '次迭代:最优解位置在' + str(pg) + ',最优解的适应度值为:' + str(best))
        plt.plot([t for t in range(self.T)], best_all)
        plt.ylabel('适应度值')
        plt.xlabel('迭代次数')
        plt.title('粒子群适应度趋势')
        plt.show()

三、实验操作

本文选取一个适应度函数作为实验对象:

X可以选取不同的值,比如X=5

理论上在上述范围内,其函数最小值为:

使用粒子群优化时N=1000,其它参数默认。其适应度函数值如下图所示。

可以看出来在迭代几次后适应度值回归0,可以看出粒子群还是很强大的。最终结果:第99次迭代:最优解位置在[-0.0033824972144645693, -0.00041073819884876104, -0.020837825233968172, -0.004563775182149339, -0.0014281389517050655],最优解的适应度值为:8.442317543610645e-06,可以看出最终结果都接近0,还是强大。

最后模拟实验了一把x=20,一直没收敛,最终把w改为0.15,才快速收敛,看来还是要调参。

最终结果:第99次迭代:最优解位置在[0.2116144935400703, 0.07887187671813765, -1.3609859231410183e-08, -1.799398730028292e-07, -0.11696106146417741, 0.10037271577264674, -0.017925057083705564, -0.02802360488939756, -0.005706816942171255, -0.013489326069795754, 0.05147854918903612, 0.0812079535495765, -0.014420970040807935, 6.384991604874465e-05, 0.00505764782058281, -0.01506357441766914, 0.0011273641957984912, 0.07792954674542905, -0.0015019673080418508, 0.022567192289875606],最优解的适应度值为:0.09236825011895983

赞 赏 作 者

Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

推荐阅读:

Python 任务调度利器:APScheduler

穿越熊市?用 Python 自制指数估值图

抄底美股?用 Python 分析美股实际收益率

Python 中如何安全地进行编译和反编译?

▼点击成为社区注册会员   喜欢文章,点个在看

  • 6
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要使用Python实现粒子群算法,你可以按照以下步骤进行操作: 1. 首先,创建一个Particle类来表示每个粒子。这个类应该具有初始化方法(init),其中包括粒子的维度(dim)、位置范围(minx和maxx)、当前位置(pos)、当前速度(vel)、个体最优位置(best_pos)和个体最优值(best_val)。可以参考上述的代码来实现这个类。 2. 然后,创建一个PSO类来表示粒子群算法。这个类应该具有初始化方法(init),其中包括粒子的维度(dim)、粒子群的大小(size)、迭代次数(iter_num)、最大速度(max_vel)、位置范围(minx和maxx)以及变异概率(pm)。可以参考上述的代码来实现这个类。 3. 在PSO类中,你需要定义一个run方法来执行粒子群算法的主要逻辑。在这个方法中,你需要创建一群粒子,并在每次迭代中更新每个粒子的速度和位置。你还需要更新每个粒子的个体最优位置和最优值,并记录全局最优位置和最优值。可以参考以下伪代码来实现这个方法: - 初始化一个空的粒子群列表。 - 创建size个粒子并添加到粒子群列表中。 - 初始化全局最优位置和最优值为第一个粒子的位置和值。 - 进入迭代循环,重复iter_num次: - 对于每个粒子: - 计算粒子的速度。 - 更新粒子的位置。 - 更新粒子的个体最优位置和最优值。 - 更新全局最优位置和最优值。 - 返回全局最优位置和最优值。 4. 最后,你可以在主函数(if __name__ == '__main__')中创建一个PSO对象,并调用run方法来运行粒子群算法。你需要提供适当的参数,例如维度、粒子群大小、迭代次数、最大速度、位置范围和变异概率。 通过以上步骤,你就可以用Python实现粒子群算法了。参考上述代码和中的示例来编写你自己的代码。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值