目录

  • 1粒子群算法简介
  • 2算法原理
  • 3迭代公式
  • 4算法流程
  • 5实例计算
  • 6代码实现
  • 6.1 基于numpy
  • 6.2 基于sko.pso


1粒子群算法简介

粒子群算法(Particle Swarm Optimization,简称PSO)是1995年Eberhart博士和Kennedy博士一起提出的。粒子群算法是通过模拟鸟群捕食行为设计的一种群智能算法。区域内有大大小小不同的食物源,鸟群的任务是找到最大的食物源(全局最优解),鸟群的任务是找到这个食物源。鸟群在整个搜寻的过程中,通过相互传递各自位置的信息,让其他的鸟知道食物源的位置最终,整个鸟群都能聚集在食物源周围,即我们所说的找到了最优解,问题收敛。学者受自然界的启发开发了诸多类似智能算法,如蚁群算法、布谷鸟搜索算法、鱼群算法、捕猎算法等等。

2算法原理

这是一个根据鸟群觅食行为衍生出启发式的算法,现在有一群鸟,他们一起出发觅食,目标就是找到可行域食物最丰富的位置。小鸟们在同一个微信群聊中,可以不断共享自己找到的事物最丰富的地方。策略如下:
  1. 每只鸟随机找一个地方,按照一个随机的方向出发。
  2. 每飞一分钟后, 每只鸟将自己找到的最优地点以及事物存量共享到群里,然后计算出群体找到的最优位置。
  3. 每只鸟回顾自己的路径,综合考虑自己走过的最优的位置和群体最优位置决定下一步的方向。
  4. 如果大家都到了同一个地方附近,就停止寻找,否则重复2 ,3 步。

整个群体的位置更新如下图,每一个红点即一个粒子: (图片来自 scikit-opt)

粒子群算法 BP神经网络 粒子群算法的概念_算法


而某一只鸟(其中一个粒子)的位置更新方法如下图:

粒子群算法 BP神经网络 粒子群算法的概念_算法_02

3迭代公式

迭代公式非常简单明了

每一次的速度更新公式:

粒子群算法 BP神经网络 粒子群算法的概念_算法_03


位置更新公式:

粒子群算法 BP神经网络 粒子群算法的概念_人工智能_04


c1,c2-加速常数,调节学习最大步长

r1,r2-两个随机函数,取值范围[0,1],以增加搜索随机性

w-惯性权重,非负数,调节对解空间的搜索范围。

那怎么判断一个位置的优劣呢? 需要求解的最小化目标函数称为适应度函数, 将粒子的位置带入适应度函数,结果越小越优。

4算法流程

粒子群算法 BP神经网络 粒子群算法的概念_粒子群算法 BP神经网络_05

5实例计算

现在我们举一个简单的例子, 求解一维优化问题计算的目标函数粒子群算法 BP神经网络 粒子群算法的概念_粒子群算法 BP神经网络_06的最小值点。

初始化两个粒子,位置分别是粒子群算法 BP神经网络 粒子群算法的概念_粒子群算法 BP神经网络_07, 初始速度为粒子群算法 BP神经网络 粒子群算法的概念_粒子群算法 BP神经网络_08 ,为了计算简便粒子群算法 BP神经网络 粒子群算法的概念_算法_09参数值取1.

粒子群算法 BP神经网络 粒子群算法的概念_python_10

6代码实现

6.1 基于numpy
import numpy as np 
import random 

# pso  
def suit(x):
    x1, x2=x
    return -(x1-10) ** 2 + -(x2 - 3) ** 2  # + -x3 ** 2

def best_p(current_p,person_best): #  
    x = np.zeros_like(current_p) 
    n,d = current_p.shape
    for i in range(n):# 每个粒子比较一次
        a = current_p[i]
        b = person_best[i]
        if suit(b)>suit(a):
            x[i] = b
        else: x[i]= a
    return x 
        
def global_b(person_best): # n*d 
    n,d= person_best.shape 
    s = []
    for j in range(n):
        s.append(suit(person_best[j]))        
    i = np.array(s).argmax()
    x = np.array(person_best[i])
    return x         
# init  
n = 40 # 粒子个数
d = 2
current_v =  np.array([[random.randint(1, 100) for i in range(n)]]).reshape(-1,d)
current_p = np.array([[random.randint(1, 100) for i in range(n)]]).reshape(-1,d)
person_best = current_p
global_best = global_b(person_best)  
T = 0   
w=1   
while  T<100000:        
    # if  all([current_p[i][0]==current_p[0][0] for i in range(len(current_p))]):
    #     print(T,current_p)
    #     break
    if sum(person_best.std(axis=0))<.1:
        break        
    else:    
        w = w*0.99996;r1 = random.random(); r2 = random.random()
        current_v = w*current_v + r1*(person_best-current_p)+ r1*(global_best - current_p)
        #  w = w*0.999
        # current_v = w*current_v +(person_best-current_p)+(global_best - current_p)
        current_p = current_p + current_v
        person_best =  best_p(current_p, person_best)
        global_best = global_b(person_best) 
        #current_v = current_v + 2* (person_best- current_p)+2*(global_best- current_p)
        T+=1 
print(T, person_best)
6.2 基于sko.pso

python sko库中包含了常用的启发式算法, 也包含粒子群算法PSO,可以直接调用,非常快捷方便 。

from sko.PSO import PSO
def demo_func(x):
    x1, x2, x3 = x
    return (x1-5) ** 2 + (x2 - 2) ** 2 + (x3-19) ** 2
pso = PSO(func=demo_func, dim=3)
fitness = pso.fit()
print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y) 

>>>best_x is  [ 4.99981675  2.00044853 18.99955148] best_y is [4.35931123e-07]