这篇文章将从灰狼算法公式与原理,代码实现与注释,参数调优与测试三方面带你解开灰狼算法的”神秘面纱“。
注:第一部分含AI生成,内容或许与本站或外站内容相似,因此本文会对第一部分做更为详细的解释。
一、灰狼算法公式与原理
灰狼优化算法(Grey Wolf Optimizer, GWO)是一种模仿灰狼狩猎行为的群体智能优化算法,由Seyedali Mirjalili等人在2014年提出。灰狼优化算法主要模拟了灰狼的社会等级结构和狩猎策略,用于解决各种优化问题。在灰狼优化算法中,搜索代理(灰狼)根据Alpha(α)、Beta(β)和Delta(δ)的位置来更新自己的位置,这种更新方式反映了狩猎过程中的跟随行为。
灰狼群的社会等级通常分为四个等级:
- Alpha(α):群体的领袖,负责决策和指导群体行动。
- Beta(β):从属狼,辅助Alpha制定决策或其他种群活动。
- Delta(δ):执行具体任务,如警戒、照顾幼崽等。
- Omega(ω):位于社会层级最底层,通常承担群体中最低级的工作。
在GWO中,解的搜索代理被视为灰狼群体中的个体,根据它们的适应度被赋予不同的社会地位,最优的三个解分别被标记为α、β、δ。这些领导灰狼引导其他灰狼向更优解区域迁移。
灰狼优化算法的核心是位置更新公式,这些公式模拟了灰狼在狩猎过程中的行为。以下是一些关键公式的描述:
除了前三头狼是从族群中推选出来的,不需要进行位置更新【即将每一次位置更新后得到适应度最小的三个解位置视为前三头狼】,其余狼的位置均需要根据前三头狼的位置来做调整。Omega狼的位置更新公式中涉及到2个参数,即A和C,A的值决定了灰狼是向猎物靠近还是远离,而C的值则决定了灰狼当前位置对猎物影响的随机权重,其计算公式如下:
其中,r1和r1是介于0和1之间的随机数【在python中用np.random.rand(dim)表示,dim表示的是解空间的维度】;a是收敛因子,初始值为2,随着迭代次数增大线性减小到0【a的作用是随着迭代次数增加逐渐减小其他狼与前三头狼之间的距离,逐渐缩小包围圈,即从广泛搜索过渡到局部搜索】。
Omega狼有了A和C两个参数后,开始根据前三头狼的位置进行调整,公式如下:
其中,D表示当前这只狼与前三头狼中的某一头狼之间的距离,Xa为前三头狼中的某一头狼所在位置,Xi为当前这只狼所在位置;Xa,i为当前这只狼根据前三头狼中的某一头狼所处位置决定前往的位置【当前这只狼下一步所属位置是根据前三头狼所处位置综合判断得来的,即三个Xa,i相加取平均后得到的才是这只狼下一步的位置】。
二、代码实现与注释
import numpy as np
import time
from matplotlib import pyplot as plt
def D_los_fitness(X):
"""
使用快捷键 ctrl+‘/’ 快速注释一行代码
:param X: 当前这只狼的位置
:return: 适应度
"""
"""step函数,维度取30,上下界取【-100,100】,最优适应度为0,最优解全为0"""
# fitness = np.sum(np.power(np.abs(X + 0.5), 2))
"""sphere函数,维度取30,上下界取【-5.12,5.12】,最优适应度为0,最优解全为0"""
fitness = np.sum(X**2)
"""rastrigin函数,维度取30,上下界取【-5.12,5.12】,最优适应度为0,最优解全为0"""
# fitness = np.sum(X ** 2 - 10 * np.cos(2 * np.pi * X) + 10)
return fitness
def calculate_fitness(X, pop, func):
fitness = np.zeros([pop, 1])
for i in range(pop):
fitness[i] = func(X[i, :])
return fitness
def initial(pop, dim, lb, ub):
X = lb + (ub - lb) * np.random.rand(pop, dim) # 初始化种群
return X
def sort_fitness(fit):
fitness = np.sort(fit, axis=0)
index = np.argsort(fit, axis=0) # 获取升序排序后每个数值在原来数组之中的索引
return fitness, index
def sort_position(X, index):
X_new = np.zeros(X.shape)
for i in range(X.shape[0]):
X_new[i, :] = X[index[i], :]
return X_new
def gwo(dims, lbs, ubs):
# 记录程序开始运行时间
t1 = time.time()
"""设置参数"""
pop, iters, dim, lb, ub = 100, 500, dims, lbs, ubs # 分别为种群数量、最大迭代次数、解空间维度、解的下界、解的上界
a = 2 # 收敛因子
func = D_los_fitness # 适应度函数
"""计算初始种群的适应度"""
"""
X_old:狼群位置更新前的位置
fitness_old:狼群更新前位置对应的适应度大小
"""
X_old = initial(pop=pop, dim=dim, lb=lb, ub=ub) # 初始化种群
fitness_old = calculate_fitness(X=X_old, pop=pop, func=func) # 计算初始种群适应度
best_position = None # 记录最优解位置
Curve = np.zeros(iters) # 记录每一次迭代获取的最优适应度,用于绘制适应度曲线
for p in range(iters):
print(p)
"""对种群进行排序,找出三头最优狼"""
"""
62、63行代码是对种群适应度从小到大排序,以获取前三个最优适应度位置最优前三头狼
"""
fitness_old, sortIndex = sort_fitness(fitness_old) # 对更新前的种群适应度值排序
X_old = sort_position(X_old, sortIndex) # 对更新前的种群位置排序
best_wolf_position = X_old[:3] # best_wolf_position的形状为3×dim
"""更新A和C"""
A = 2 * (a - a * p / iters) * np.random.rand(3, 1) - (a - a * p / iters) # A的形状为3×3
C = 2 * np.random.rand(3, 1) # C的形状为3×3
"""更新狼的位置"""
for i in range(3, pop):
X_ave = best_wolf_position - A * np.abs(C * best_wolf_position - X_old[i])
X_old[i] = np.mean(X_ave, axis=0) # 获取当前这只狼更新后的位置
"""重新计算适应度"""
fitness_old = calculate_fitness(X=X_old, pop=pop, func=func)
"""找到并记录下这一次迭代的最优解"""
best_position = X_old[np.argmin(fitness_old)] # 获取最优解位置
Curve[p] = np.min(fitness_old) # 获取最优解
# 结果输出与绘图
t2 = time.time()
print("耗时:", t2 - t1)
print('最优适应度值:', Curve[-1])
print('最优解[x1,x2]:', best_position)
print('Curve:', len(Curve))
# 绘制适应度曲线
plt.figure(1)
plt.plot(Curve, 'r-', linewidth=2)
plt.xlabel('Iteration', fontsize='medium')
plt.ylabel("Fitness", fontsize='medium')
plt.grid()
plt.title('SSA', fontsize='large')
plt.show()
return best_position, Curve
"""适应度函数的维度、下界和上界,当需要更换适应度函数时,只需要修改这三个参数以及适应度函数主体即可,一般不修改gwo函数内部参数"""
dim_external = 30
lb_external = np.full(dim_external, -5.12)
ub_external = np.full(dim_external, 5.12)
gwo(dim_external, lb_external, ub_external)
上述代码直接复制粘贴即可使用,注意以下事项:
1、记得安装numpy、matplotlib库(scipy库可以不用安装)。
2、切换其他函数测试时,只需要修改dim_external、lb_external、ub_external里面的数值以及D_los_fitness函数体内部的函数实现即可。文章代码中给出了三个测试函数,分别是step函数、sphere函数以及rastrigin函数,它们的最优适应度都是0,解空间分别为[-100,100]、[-5.12,-5.12]、[-5.12,-5.12],维度都是30。
3、当结果不正确时(几乎不会发生),可以尝试修改gwo函数内部的参数,不过谨慎修改!
程序运行结果如下:
三、参数调优与测试
灰狼算法参数较少,共涉及以下几个重要参数:
- 种群数量:选择适当的种群大小极其重要,直接影响搜索广度和算法的计算负担。种群大小需足以探索解空间的不同区域,同时避免过大增加计算复杂度。
- 最大迭代次数:算法运行的总迭代次数,决定了算法的优化时间和深度。
- 收敛因子:初始值为2,随着迭代次数增大线性减小到0。它控制了算法的勘探(exploration)和开发(exploitation)能力。
一般而言,常规灰狼算法不需要进行参数调优,种群数量一般取100,迭代次数一般取500,收敛因子一般取2。当问题简单时,种群数量和最大迭代次数可以适当减小,相反则增大。不过,一般不调整种群数量和最大迭代次数,而是通过其他方法,如引入混沌序列、修改收敛因子规则、引入变异特性等来改进算法性能。
上述代码经测试,偶尔会出现陷入局部解的情况(大约运行了50次出现了一次),这是因为α狼不一定是全局最优点, 在不断的迭代中,ω不断逼近前3匹狼, 导致GWO算法陷入局部最优解。后续,我将在专栏给出改进的灰狼算法及其Python代码,并结合实际案例引出之后要写的一个较新的算法——麻雀算法及其变种混沌麻雀算法。
写在最后,如果这篇文章对你有帮助,还请点赞收藏加关注,感谢客官老爷!