AI有很多定义。根据Merrian-Webster字典,人工智能是计算机科学的一个大领域,它模拟计算机中的智能行为。基于此,一种基于元启发式算法的算法实现称为粒子群优化(最初提出模拟鸟类寻找食物,鱼群的运动等)能够模拟群体的行为,以迭代地优化数值问题。例如,它可以被分类为群体智能算法,如蚁群算法,人工蜂群算法和细菌觅食算法。
由J. Kennedy和R.Eberhart于1995年提出的文章“粒子群优化”因其持续的优化过程(允许多目标的变化)而变得非常受欢迎。在不断搜索最佳解决方案的过程中,该方法将粒子(在本例中表示为A(x,y)位置)移动,并在每次迭代中计算出一定的速度。预期的最终结果是粒子群收敛到最佳解。重要的是要提到PSO不使用梯度下降,因此一旦它不要求问题必须是可微分的,它就可以用于非线性问题。
算法
让我们观察伪代码
首先,在2个for循环中,它初始化粒子的位置,在允许的范围内对其所有维度进行随机均匀分布(有些问题需要处理到几个维度)。然后,对于每个粒子,它计算它的适应度值,并与自己的最佳位置(p_best值是该特定粒子有史以来的最佳位置)进行比较,然后在g_best中选择所有粒子的最佳位置。
让我们仔细研究定义粒子维度下一次迭代速度的等式:Vᵢ(k + 1)是下一个迭代速度
W是惯性参数。此参数影响最后一个速度值给出的运动传播。
C 1和C 2是加速系数。C 1值给出了个体最佳值的重要性,C 2是群体最佳值的重要性。
Pᵢ是最佳的个体位置,Pg是所有粒子的最佳位置。在等式中,测量每个参数与粒子实际位置的距离。
rand 1和rand 2是随机数,其中0≤rand= 1,它们控制着每个值的影响:群体和个体,如下所示。
然后计算新粒子的位置,直到指定的迭代次数或达到误差标准为止。
实现
我们的目标是找到某个函数的最小点。在这种情况下,函数是f(x,y)=x²+y²+ 1.因此,算法将使用2维位置数组,适应度值将是Z坐标。另外,我们知道我们的目标是找到坐标[0,0],它是f(x,y)的最小值。
为了在python中实现该算法,我们使用了OOP,以帮助我们实现和理解Python代码中的所有步骤。在这里,使用numpy库来处理多维空间中的数组操作。
x²+y²(Wolframalpha)的3D图形
Contour plot of x² + y² (Wolframalpha)
让我们从Particle类开始。
粒子
当一个粒子被自动启动时,我们对限制在-50到+50范围内的2个位置进行排序。pbest_position(这是粒子的最佳个体位置)开始于初始位置,同样,当我们正在寻找最小值时,pbest_value被+ inf初始化(可以是任何较大的值)。还定义了一个__str__()方法来打印的实际位置和最好的个体值。move()方法添加位置向量和在搜索中计算的维度速度。
搜索空间
搜索空间是控制算法例程的实体。在这个实现中,它负责保留所有粒子,识别和设置所有粒子的个体最佳位置值,管理目标误差准则,计算最佳全局值,设置最佳全局位置。在resume中,它封装了所有主要步骤。
方法set_pbset和set_gbest具有类似的实现方式。首先,它遍历所有粒子并计算粒子位置的适应度值,并与最佳个体位置(在set_pbest处)和最佳全局位置(在set_gbest处)进行比较。
方法move_particles计算每个维度中每个粒子的新矢量速度。
主循环
首先,它启动一个目标为1的搜索空间。这个目标表示适应度值上的目标,这意味着目标是f(x,y) = 1。然后,该算法将找到x和y的哪个值给出的结果等于1,就像前面在函数形状中所示的那样,我们希望找到最小值。Contour图也向我们显示我们想要找到的值是[0,0]。目标误差和粒子数(n_particles)将由用户设置。然后使用列表生成器启动所有粒子并在启动迭代后启动。
首先,在所有迭代中,找到最佳的个体位置和最佳的全局位置来评估目标误差标准。如果这个标准没有达到最小误差,粒子将计算移动的速度,然后停在一个新的位置,直到迭代次数或达到最小误差标准。最后一行只是打印出最好的结果。
完整Python代码
import randomimport numpy as np W = 0.5c1 = 0.8c2 = 0.9 n_iterations = int(input('Inform the number of iterations: '))target_error = float(input('Inform the target error: '))n_particles = int(input('Inform the number of particles: '))class Particle(): def __init__(self): self.position = np.array([(-1) ** (bool(random.getrandbits(1))) * random.random()*50, (-1)**(bool(random.getrandbits(1))) * random.random()*50]) self.pbest_position = self.position self.pbest_value = float('inf') self.velocity = np.array([0,0]) def __str__(self): print('I am at ', self.position, ' meu pbest is ', self.pbest_position) def move(self): self.position = self.position + self.velocityclass Space(): def __init__(self, target, target_error, n_particles): self.target = target self.target_error = target_error self.n_particles = n_particles self.particles = [] self.gbest_value = float('inf') self.gbest_position = np.array([random.random()*50, random.random()*50]) def print_particles(self): for particle in self.particles: particle.__str__() def fitness(self, particle): return particle.position[0] ** 2 + particle.position[1] ** 2 + 1 def set_pbest(self): for particle in self.particles: fitness_cadidate = self.fitness(particle) if(particle.pbest_value > fitness_cadidate): particle.pbest_value = fitness_cadidate particle.pbest_position = particle.position def set_gbest(self): for particle in self.particles: best_fitness_cadidate = self.fitness(particle) if(self.gbest_value > best_fitness_cadidate): self.gbest_value = best_fitness_cadidate self.gbest_position = particle.position def move_particles(self): for particle in self.particles: global W new_velocity = (W*particle.velocity) + (c1*random.random()) * (particle.pbest_position - particle.position) + \ (random.random()*c2) * (self.gbest_position - particle.position) particle.velocity = new_velocity particle.move() search_space = Space(1, target_error, n_particles)particles_vector = [Particle() for _ in range(search_space.n_particles)]search_space.particles = particles_vectorsearch_space.print_particles()iteration = 0while(iteration < n_iterations):="" search_space.set_pbest()="" search_space.set_gbest()="" if(abs(search_space.gbest_value="" -="" search_space.target)=""><= search_space.target_error):="" break="" search_space.move_particles()="" iteration="" +="1" print('the="" best="" solution="" is:="" ',="" search_space.gbest_position,="" '="" in="" n_iterations:="" ',="">=>
W,C 1和C 2的值是手工选择的,所以要小心选择,因为它们可能引起很长的计算时间。
结果
使用python解释器,我们输入迭代次数、目标误差标准和粒子数。
然后,它打印出最好的结果:The best solution is: [ 5.06237850e-04 -1.14851873e-05] in n_iterations: 22