粒子群算法详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lyf52010/article/details/82859048

参考链接:https://blog.csdn.net/zuochao_2013/article/details/53431767?ref=myread

❃粒子群算法(particleswarm optimization,PSO)由Kennedy和Eberhart在1995年提出,该算法对于Hepper的模拟鸟群(鱼群)的模型进行修正,以使粒子能够飞向解空间,并在最好解处降落,从而得到了粒子群优化算法。

❃同遗传算法类似,也是一种基于群体叠代的,但并没有遗传算法用的交叉以及变异,而是粒子在解空间追随最优的粒子进行搜索。

❃PSO的优势在于简单,容易实现,无需梯度信息,参数少,特别是其天然的实数编码特点特别适合于处理实优化问题。同时又有深刻的智能背景,既适合科学研究,又特别适合工程应用。

设想这样一个场景:一群鸟在随机的搜索食物。在这个区域里只有一块食物,所有的鸟都不知道食物在哪。但是它们知道自己当前的位置距离食物还有多远。

                         那么找到食物的最优策略是什么?

最简单有效的就是搜寻目前离食物最近的鸟的周围区域。

二.算法介绍

(1)简述

❃每个寻优的问题解都被想像成一只鸟,称为“粒子”。所有粒子都在一个D维空间进行搜索。

❃所有的粒子都由一个fitness-function确定适应值以判断目前的位置好坏。

❃每一个粒子必须赋予记忆功能,能记住所搜寻到的最佳位置。

❃每一个粒子还有一个速度以决定飞行的距离和方向。这个速度根据它本身的飞行经验以及同伴的飞行经验进行动态调整。 

(2)基本PSO算法

  a.  D维空间中,有m个粒子;

  粒子i位置:xi=(xi1,xi2,…xiD)

  粒子i速度:vi=(vi1,vi2,…viD),1≤i≤m,1 ≤d ≤D

  粒子i经历过的历史最好位置:pi=(pi1,pi2,…piD)

  群体内(或领域内)所有粒子所经历过的最好位置:

  pg =(pg1,pg2,…pgD)

  PS:一般来说,粒子的位置和速度都是在连续的实数空间内进行取值。

   b.基本PSO公式

(3)基本PSO算法流程图

关于每个粒子的更新速度和位置的公式如下:

三.简单应用

  

(1)•编码:因为问题的维数为5,所以每个粒子为5维的实数向量。

(2)•初始化范围:根据问题要求,设定为[-30,30]。根据前面的参数分析,我们知道,可以将最大速度设定为Vmax=60。

(3)•种群大小:为了说明方便,这里采用一个较小的种群规模,m=5。

(4)•停止准则:设定为最大迭代次数100次。

(5)•惯性权重:采用固定权重0.5。

(6)邻域拓扑结构:使用星形拓扑结构,即全局版本的粒子群优化算法

算法执行的过程如下:


class Particle:
    '''
    individual Particle
    '''
    
    # 类变量,所有粒子共享
    globle_best_position = np.zeros(3) # 全局最优位置
    globle_best_fitness = 0 # 全局最优适应度值
    
    def __init__(self, vardim, bound, fixed_params, long):
        '''
        vardim: dimension of variables
        bound: boundaries of variables
        fitness: fitness value of Particle
        position: position of Particle
        velocity: speed of Particle
        bestPosition: the best position of Particle
        bestFitness: the best fitness of Particle
        '''
        self.vardim = vardim # 自变量维度08/7
        self.bound = bound # 自变量的取值范围
        self.fitness = 0 # 粒子的适应度值
        self.spp = 0 # 约束条件1
        self.tor = 0 # 约束条件2
        self.position = np.zeros(vardim) # 粒子的位置
        self.velocity = np.zeros(vardim) # 粒子的速度
        self.bestPosition = np.zeros(vardim) # 个体最优位置
        self.bestFitness = 0 # 个体最优适应度值
        self.fixed_params = fixed_params # 除了自变量外的其他固定参数
        self.restart_count = 0 # 粒子不满足约束条件重新生成的次数
        self.long = long  # 动态模型训练数据长度
        
    def generate(self):
        '''
        generate a rondom position
        '''
        # 随机种子
        np.random.seed(int(math.modf(time.time())[0] * 10000000))
        self.position = np.random.uniform(self.bound[0], self.bound[1], self.vardim)
        self.velocity = np.random.uniform(self.bound[0], self.bound[1], self.vardim) / 10
        # calculateFitness()
        
    # 约束条件的验证
    def verification(self):
        '''
        if generate a invaild individual, recall to generate again
        '''
        # 自变量h,i,j约束条件
        for i in range(self.vardim):
            if self.position[i] < self.bound[0,i] or self.position[i] > self.bound[1,i]:               
                return False 
            
        # 因变量a,m约束条件
        if self.spp < SPP_min or self.spp > SPP_max or \
           self.tor < TOR_min or self.tor > TOR_max:
                return False
        
        return True
            
    # 计算适应度值
    def calculateFitness(self):
        '''
        calculate the fitness of the Particle
        '''
        self.fitness, self.spp, self.tor = ObjFunction(self.position, self.fixed_params, self.long)
        
        # 约束条件
        # 若不满足约束条件则重新生成一个新的随机粒子,直到满足约束条件为止
        while self.verification() == False:       
            self.restart_count += 1
            #print self.restart_count
            self.generate()
            self.fitness, self.spp, self.tor = ObjFunction(self.position, self.fixed_params, self.long)
            
        #print(self.position, self.fitness)
        #print("%f %d %d" % (self.fitness, self.spp, self.tor))
        
        # 更新个体最优位置和最优适应度值
        if self.fitness > self.bestFitness:
            self.bestFitness = self.fitness
            self.bestPosition = self.position

            # 更新全局最优位置和最优适应度值
            if self.bestFitness > Particle.globle_best_fitness:
                Particle.globle_best_fitness = self.bestFitness
                Particle.globle_best_position = self.bestPosition
                
                #print(self.position, self.fixed_params)
                #print("globle_best_fitness: %f %d %d" % (self.fitness, self.spp, self.tor))

class ParticleSwarmOptimization:

    '''
    the class for Particle Swarm Optimization

    '''

    def __init__(self, p_size, vardim, bound, params, fixed_params, data_id, turn, terminal_round, max_round, verbose ,long):

        '''
        p_size: population size
        vardim: dimension of variables
        bound: boundaries of variables
        params: algorithm required parameters, it is a list which is consisting of[w, c1, c2]
        fixed_params: It is a list which is a row of CSV file drop [h,i,j] columns. 
        '''
        self.p_size = p_size # 种群大小,即粒子数
        self.vardim = vardim # 自变量个数
        self.bound = bound # 自变量范围
        self.params = params # 粒子群优化算法的参数 [w, c1, c2]
        self.population = []   # 种群
        self.fixed_params = fixed_params # 模型值中除了自变量外的其他固定输入变量
        self.data_id = data_id
        self.turn = turn # 粒子群优化次数
        self.terminal_round = terminal_round # 连续n轮迭代最优适应度值不变则终止迭代--终止迭代条件
        self.max_round = max_round # 最多迭代的次数
        self.verbose = verbose # 是否显示优化过程
        self.long = long  # 动态模型训练数据长度
        

    # 初始化粒子群
    def initialize(self):
        '''
        initialize the population of pso
        '''
        for i in range(0, self.p_size):
            particle = Particle(self.vardim, self.bound, self.fixed_params, self.long)
            particle.generate()
            particle.calculateFitness()
            self.population.append(particle)
    
    # 更新种群粒子位置和速度以及适应度值
    def update(self):
        '''
        update the population of pso
        '''
        
        for i in range(0, self.p_size):
            self.population[i].velocity = self.params[0] * self.population[i].velocity + \
                                              self.params[1] * np.random.random(self.vardim) * (self.population[i].bestPosition - self.population[i].position) + \
                                              self.params[2] * np.random.random(self.vardim) * (Particle.globle_best_position - self.population[i].position)
            
            self.population[i].position = self.population[i].position + self.population[i].velocity
                 
            self.population[i].calculateFitness()
            
            #print(self.population[i].position, self.population[i].fitness, self.population[i].bestFitness)
        #print(timer() - start)
        
    # 运行粒子群算法        
    def solve(self):
        '''
        the evolution process of the pso algorithm
        '''
        self.iter = 0
        self.initialize()
        round_best_fitness =  Particle.globle_best_fitness #  当前迭代的最优适应度值
        count = 0

        # 终止条件:连续n轮迭代最优适应度值不变或者达到最大迭代次数则终止迭代
        while count < self.terminal_round and self.iter < self.max_round:
            self.iter += 1
            self.update()
            
            # 更新最优适应度值没有提高的轮数
            if round_best_fitness < Particle.globle_best_fitness:
                count = 0
            else:
                count += 1
                
            round_best_fitness =  Particle.globle_best_fitness
            
            if self.verbose == True:
                print("Row: %d Turn: %d Itr %d: opt value: %f Pos: " % \
                     (self.data_id, self.turn, self.iter, Particle.globle_best_fitness), Particle.globle_best_position)

        total_restart_count = 0
        for i in range(0, self.p_size):
            total_restart_count += self.population[i].restart_count

猜你喜欢

转载自blog.csdn.net/lyf52010/article/details/82859048