优化算法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优化算法相关的知识,希望对你有一定的参考价值。
参考技术A SGD算法中的一个关键参数是学习率。之前,我们介绍的SGD使用固定的学习率。在实践中,有必要随着时间的推移逐渐降低学习率,因此我们将第 k 步迭代的学习率记作 ϵ k 。这是因为SGD中梯度估计引入的噪声源(m 个训练样本的随机采样)并不会在极小点处消失。相比之下,当我们使用批量梯度下降到达极小点时,整个代价函数的真实梯度会变得很小,之后为 0,因此批量梯度下降可以使用固定的学习率。保证SGD收敛的一个充分条件是
若 ϵ 0 太大,学习曲线将会剧烈振荡,代价函数值通常会明显增加。温和的振荡是良好的,容易在训练随机代价函数(例如使用Dropout的代价函数)时出现。如果学习率太小,那么学习过程会很缓慢。如果初始学习率太低,那么学习可能会卡在一个相当高的代价值。通常,就总训练时间和最终代价值而言,最优初始学习率会高于大约迭代 100 次左右后达到最佳效果的学习率。因此,通常最好是检测最早的几轮迭代,选择一个比在效果上表现最佳的学习率更大的学习率,但又不能太大导致严重的震荡。
虽然随机梯度下降仍然是非常受欢迎的优化方法,但其学习过程有时会很慢。动量方法 (Polyak, 1964) 旨在加速学习,特别是处理高曲率、小但一致的梯度,或是带噪声的梯度。动量算法积累了之前梯度指数级衰减的移动平均,并且继续沿该方向移动。动量的效果如图8.5所示
受 Nesterov 加速梯度算法 (Nesterov, 1983, 2004) 启发,提出了动量算法的一个变种。这种情况的更新规则如下:
其中参数 α 和 ϵ 发挥了和标准动量方法中类似的作用。Nesterov 动量和标准动量之间的区别体现在梯度计算上。Nesterov 动量中,梯度计算在施加当前速度之后。因此,Nesterov 动量可以解释为往标准动量方法中添加了一个校正因子。完整的Nesterov动量算法如算法3.2所示
初始点能够决定算法是否收敛,有些初始点十分不稳定,使得该算法会遭遇数值困难,并完全失败。当学习收敛时,初始点可以决定学习收敛得多快,以及是否收敛到一个代价高或低的点。此外,差不多代价的点可以具有区别极大的泛化误差,初始点也可以影响泛化。
也许完全确知的唯一特性是初始参数需要在不同单元间 ‘‘破坏对称性’’。如果具有相同激活函数的两个隐藏单元连接到相同的输入,那么这些单元必须具有不同的初始参数。如果它们具有相同的初始参数,然后应用到确定性损失和模型的确定性学习算法将一直以相同的方式更新这两个单元。即使模型或训练算法能够使用随机性为不同的单元计算不同的更新(例如使用Dropout的训练),通常来说,最好还是初始化每个单元使其和其他单元计算不同的函数。这或许有助于确保没有输入模式
丢失在前向传播的零空间中,没有梯度模式丢失在反向传播的零空间中。每个单元计算不同函数的目标促使了参数的随机初始化。我们可以明确地搜索一大组彼此互不相同的基函数,但这经常会导致明显的计算代价。例如,如果我们有和输出一样多的输入,我们可以使用 Gram-Schmidt 正交化于初始的权重矩阵,保证每个单元计算彼此非常不同的函数。在高维空间上使用高熵分布来随机初始化,计算代价小并且不太可能分配单元计算彼此相同的函数。
通常情况下,我们可以为每个单元的偏置设置启发式挑选的常数,仅随机初始化权重。额外的参数(例如用于编码预测条件方差的参数)通常和偏置一样设置为启发式选择的常数。
我们几乎总是初始化模型的权重为高斯或均匀分布中随机抽取的值。高斯或均匀分布的选择似乎不会有很大的差别,但也没有被详尽地研究。然而,初始分布的大小确实对优化过程的结果和网络泛化能力都有很大的影响。
更大的初始权重具有更强的破坏对称性的作用,有助于避免冗余的单元。它们也有助于避免在每层线性成分的前向或反向传播中丢失信号——矩阵中更大的值在矩阵乘法中有更大的输出。如果初始权重太大,那么会在前向传播或反向传播中产生爆炸的值。在循环网络中,很大的权重也可能导致混沌(chaos)(对于输入中很小的扰动非常敏感,导致确定性前向传播过程表现随机)。在一定程度上,梯度爆炸问题可以通过梯度截断来缓解(执行梯度下降步骤之前设置梯度的阈值)。较大的权
重也会产生使得激活函数饱和的值,导致饱和单元的梯度完全丢失。这些竞争因素决定了权重的理想初始大小。
也有助于避免在每层线性成分的前向或反向传播中丢失信号——矩阵中更大的值在矩阵乘法中有更大的输出。如果初始权重太大,那么会在前向传播或反向传播中产生爆炸的值。在循环网络中,很大的权重也可能导致混沌(chaos)(对于输入中很小的扰动非常敏感,导致确定性前向传播过程表现随机)。在一定程度上,梯度爆炸问题可以通过梯度截断来缓解(执行梯度下降步骤之前设置梯度的阈值)。较大的权重也会产生使得激活函数饱和的值,导致饱和单元的梯度完全丢失。这些竞争因素决定了权重的理想初始大小。
有些启发式方法可用于选择权重的初始大小。一种初始化 m 个输入和 n 输出的全连接层的权重的启发式方法是从分布 U(−1/√ m ,
1/√ m ) 中采样权重,而 Glorot and Bengio 建议使用标准初始化
后一种启发式方法初始化所有的层,折衷于使其具有相同激活方差和使其具有相同梯度方差之间。这假设网络是不含非线性的链式矩阵乘法,据此推导得出。现实的神经网络显然会违反这个假设,但很多设计于线性模型的策略在其非线性对应中的效果也不错。
数值范围准则的一个缺点是,设置所有的初始权重具有相同的标准差,例如1/√ m ,会使得层很大时每个单一权重会变得极其小。Martens (2010) 提出了一种被称为稀疏初始化(sparse initialization)的替代方案,每个单元初始化为恰好有 k 个非零权重。这个想法保持该单元输入的总数量独立于输入数目 m,而不使单一权重元素的大小随 m 缩小。稀疏初始化有助于实现单元之间在初始化时更具多样性。但是,获得较大取值的权重也同时被加了很强的先验。因为梯度下降需要很长时间缩小 ‘‘不正确’’ 的大值,这个初始化方案可能会导致某些单元出问题,例如maxout单元有几个过滤器,互相之间必须仔细调整。
Delta-bar-delta 算法 (Jacobs, 1988) 是一个早期的在训练时适应模型参数各自学习率的启发式方法。该方法基于一个很简单的想法,如果损失对于某个给定模型参数的偏导保持相同的符号,那么学习率应该增加。如果对于该参数的偏导变化了符号,那么学习率应减小。当然,这种方法只能应用于全批量优化中。
AdaGrad 算法,如算法8.4所示,独立地适应所有模型参数的学习率,缩放每个参数反比于其所有梯度历史平方值总和的平方根 (Duchi et al., 2011)。具有损失最大偏导的参数相应地有一个快速下降的学习率,而具有小偏导的参数在学习率上有相对较小的下降。净效果是在参数空间中更为平缓的倾斜方向会取得更大的进步。
在凸优化背景中,AdaGrad 算法具有一些令人满意的理论性质。然而,经验上已经发现,对于训练深度神经网络模型而言,从训练开始时积累梯度平方会导致有效学习率过早和过量的减小。AdaGrad在某些深度学习模型上效果不错,但不是全部。
RMSProp 算法 (Hinton, 2012) 修改 AdaGrad 以在非凸设定下效果更好,改变梯度积累为指数加权的移动平均。AdaGrad旨在应用于凸问题时快速收敛。当应用于非凸函数训练神经网络时,学习轨迹可能穿过了很多不同的结构,最终到达一个局部是凸碗的区域。AdaGrad 根据平方梯度的整个历史收缩学习率,可能使得学习率在达到这样的凸结构前就变得太小了。RMSProp 使用指数衰减平均以丢弃遥远过去的历史,使其能够在找到凸碗状结构后快速收敛,它就像一个初始化于该碗状结构的 AdaGrad 算法实例。
RMSProp 的标准形式如算法8.5所示,结合 Nesterov 动量的形式如算法8.6所示。相比于 AdaGrad,使用移动平均引入了一个新的超参数ρ,用来控制移动平均的长度范围。经验上,RMSProp 已被证明是一种有效且实用的深度神经网络优化算法。目前它是深度学习从业者经常采用的优化方法之一。
Adam (Kingma and Ba, 2014) 是另一种学习率自适应的优化算法,最好被看作结合 RMSProp 和具有一些重要区别的动量的变种。首先,在 Adam 中,动量直接并入了梯度一阶矩(指数加权)的估计。将动量加入 RMSProp 最直观的方法是将动量应用于缩放后的梯度。结合缩放的动量使用没有明确的理论动机。其次,Adam 包括偏置修正,修正从原点初始化的一阶矩(动量项)和(非中心的)二阶矩的估计(算法8.7)。RMSProp 也采用了(非中心的)二阶矩估计,然而缺失了修正因子。因此,不像 Adam,RMSProp 二阶矩估计可能在训练初期有很高的偏置。Adam 通常被认为对超参数的选择相当鲁棒,尽管学习率有时需要从建议的默认修改。
目前,最流行并且使用很高的优化算法包括 SGD、具动量的 SGD、RMSProp、具动量的 RMSProp、AdaDelta 和 Adam。
智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)
文章目录
一、灰狼优化算法的实现思路
灰狼优化算法(Grey Wolf Optimizer,简称GWO)是由Seyedali Mirjalili等人于2014年提出的一种群智能优化算法,这一算法主要由自然界中的灰狼群体的捕食行为启发而来,灰狼是一种群居动物,一般群体中由5到12个个体构成,与一般动物群体不同的是,这一群体中存在十分严格的社会主导阶层,且与金字塔结构十分相似,主要由四个层级构成。
首先最高的层级可以被称为α,它们主要对种群中的各种规则进行制定,如狩猎地点、休息地点等,整个种群都会听从它们的决定。然后第二个层级被称为β,这一层级的灰狼个体主要帮助α制定相关决策,同时将各种决策上出现的问题反馈给α狼,它在整个种群中的地位仅次于α狼,因此低等级的灰狼个体也必须听命于β狼。紧接着的一个阶级为δ,这一个层级扮演着执行者的角色并将α狼与β狼制定的规则与命令付诸行动,它们可以是哨兵、侦查者、猎人,甚至是种群中受伤狼群的看护者。最后一个层级为ω,这个层级的灰狼个体为最弱势的个体,它们一般为种群中年迈或残疾的个体,因此它们只能去服从前面每个层级的灰狼个体。
结合上述思想,可以将灰狼优化算法的原理归为四个基本行为,它们分别为社会等级结构分级、搜索猎物、包围猎物以及攻击猎物,下面将分别从这四个基本行为进行介绍。
1、社会等级结构分级
该算法为了符合灰狼群体的社会等级结构,将候选解决方案的优劣性作为评判的标准,另外由于解决方案的独特性,因此将前三个等级α、β以及δ的数量设定为一个,即将候选解决方案中表现最优的方案设为α,第二个与第三个最优解决方案分别设定为β与δ,其余的解决方案则均为ω。按照等级较低的灰狼个体跟随等级较高的灰狼个体规则,ω解决方案将不断学习α、β以及δ解决方案以获得更好的表现。
2、包围猎物
针对灰狼群体包围猎物的特性,使用下列公式对其行为进行描述:
其中t为当前迭代次数,A ⃗和C ⃗为系数向量,(X_p ) ⃗为灰狼个体的位置向量,X ⃗为灰狼个体的位置信息。
A ⃗和C ⃗将分别通过下面两个公式计算得出:
其中a ⃗将随着迭代的次数由2到0线性递减,r1与r2均为0到1之间的随机向量。
3、攻击猎物
通过包围行为,所有灰狼个体将猎物控制在一个包围圈内,之后ω狼将在α、β以及δ狼的引导下进行捕猎,由于目前猎物的位置是未知的,而代表最优解决方案的灰狼α、β以及δ的位置信息是已知的,因此ω狼将通过学习灰狼α、β以及δ的位置信息来进行移动以完成对猎物的捕食。下面几个公式代表了灰狼个体的捕食行为:
由上述公式可以了解到,猎物的位置是随机的,灰狼个体将通过学习灰狼α、β以及δ的位置信息在猎物附近进行随机移动,以此来估计猎物的具体位置。
4、搜索猎物
在灰狼种群开始了对猎物的随机包围时,对猎物的搜索过程也在随之展开,由攻击猎物的原理过程可以了解到,A ⃗这一系数向量的大小将会直接影响到灰狼个体位置的移动,在整个迭代过程中,除了A ⃗的绝对值小于1外,还存在A ⃗的绝对值大于1的情况,在这种条件下,灰狼个体将向包围圈周围扩张,以此发现更多猎物可能存在的位置。即当|A|≥1时,候选解决方案倾向于偏离当前猎物,当|A|<1时,候选解决方案逐渐收敛于猎物的位置。
除系数向量A ⃗之外,还存在一个系数向量C ⃗,C ⃗通常是0到2之间的一个随机值,这一向量的角色类似于为猎物位置信息新添一个随机权重,在自然界中,灰狼种群对猎物的捕食通常不会是顺利的,有时会出现一定的障碍对整个搜索行为进行影响,使得灰狼种群无法直接快速得接近猎物,系数向量C ⃗则可以在为整个搜索过程增加一个随机性的同时使整个灰狼种群在优化过程中表现出更随机的行为,以此来探索更多区域并避免陷入局部最优。
二、算法步骤
使用灰狼优化算法对优化问题进行求解时的具体步骤可以归纳如下:
- 以种群个体的位置信息作为待优化问题的解,根据待优化问题的解的范围,随机初始化种群所有个体的位置信息;
- 初始化参数a ⃗,A ⃗和C ⃗;
- 根据待优化问题,计算每个种群个体的适应度值,并对其进行排序,适应度值越高,则个体的位置信息越接近最优解,将适应度值排在前三个个体分别设定为灰狼α、β以及δ,并保存当前最优的位置信息;
- 依次对种群中每个个体的位置信息进行更新;
- 针对每个个体更新后的位置信息,重新进行适应度值的计算,根据新的适应度值的大小更新灰狼α、β与δ的位置信息以及历史最优的位置信息,更新参数a ⃗,A ⃗和C ⃗;
- 根据迭代的次数重复步骤3到步骤5,当达到最大迭代次数时停止迭代过程,输出历史最优的位置信息,该位置信息即为算法优化后获得的最优解。
三、实例
待求解问题:
Rosenbrock’s,取值范围为[-10,10],取值范围内的理想最优解为0,将其搜索的空间维度设为20。
实现源码:
#库的导入
import numpy as np
import matplotlib.pyplot as plt
import heapq
#待求解问题,求解问题为求最小值
def function(x):
y1 = 0
for i in range(len(x)-1):
y2 = 100*((x[i+1] - x[i]**2)**2)+(x[i]-1)**2
y1 = y1 + y2
y = abs(0 - y1)
return y
m = 30 #种群数量
imax = 100 #迭代次数
dimen = 20 #解的搜索维度
rangelow = -10 #解的最小取值
rangehigh = 10 #解的最大取值
amax = 2 #系数向量初始值
#pop用于存储种群个体的位置信息,pop_fitness用于存储个体对应的适应度值
pop = np.zeros((m,dimen))
pop_fitness = np.zeros(m)
#对种群个体进行初始化并计算对应适应度值
for j in range(m):
pop[j] = np.random.uniform(low=rangelow, high=rangehigh,size=(1, dimen))
pop_fitness[j] = function(pop[j])
#allbestpop,allbestfit分别存储种群在历史迭代过程中最优个体解及对应适应度
allbestpop,allbestfit = pop[pop_fitness.argmin()].copy(),pop_fitness.min()
#通过排序找出种群中适应度值最优的前三个个体,并获得它们的位置信息
pop_fitness1 = pop_fitness.flatten()
pop_fitness1 = pop_fitness1.tolist()
three = list(map(pop_fitness1.index, heapq.nsmallest(3, pop_fitness1)))
Xalpha = pop[three[0]]
Xbeta = pop[three[1]]
Xdelta = pop[three[2]]
#his_bestfit存储每次迭代时种群历史适应度值最优的个体适应度
his_bestfit=np.zeros(imax)
#开始训练
for i in range(imax):
print("The iteration is:", i + 1)
#对系数向量的计算参数a进行计算
iratio = i / imax
a = amax * (1 - iratio)
#对每个个体进行位置更新
for j in range(m):
#分别计算在适应度值最优的前三个个体的影响下,个体的位置移动量X1、X2、X3
C1 = 2 * np.random.rand()
Dalpha = np.abs(C1 * Xalpha - pop[j])
A1 = 2 * a * np.random.rand() - a
X1 = Xalpha - A1 * Dalpha
C2 = 2 * np.random.rand()
Dbeta = np.abs(C2 * Xbeta - pop[j])
A2 = 2 * a * np.random.rand() - a
X2 = Xbeta - A2 * Dbeta
C3 = 2 * np.random.rand()
Ddelta = np.abs(C3 * Xdelta - pop[j])
A3 = 2 * a * np.random.rand() - a
X3 = Xdelta - A3 * Ddelta
#计算个体移动后的位置及适应度值
pop[j] = (X1 + X2 + X3) / 3
pop_fitness[j] = function(pop[j])
#对种群历史最优位置信息与适应度值进行更新
if pop_fitness.min() < allbestfit:
allbestfit = pop_fitness.min()
allbestpop = pop[pop_fitness.argmin()].copy()
#通过排序找出种群中适应度值最优的前三个个体,并获得它们的位置信息
pop_fitness1 = pop_fitness.flatten()
pop_fitness1 = pop_fitness1.tolist()
three = list(map(pop_fitness1.index, heapq.nsmallest(3, pop_fitness1)))
Xalpha = pop[three[0]]
Xbeta = pop[three[1]]
Xdelta = pop[three[2]]
#存储当前迭代下的种群历史最优适应度值并输出
his_bestfit[i] = allbestfit
print("The best fitness is:", allbestfit)
print("After iteration, the best pop is:",allbestpop)
print("After iteration, the best fitness is:","%e"%allbestfit)
#输出训练后种群个体适应度值的均值与标准差
mean = np.sum(pop_fitness)/m
std = np.std(pop_fitness)
print("After iteration, the mean fitness of the swarm is:","%e"%mean)
print("After iteration, the std fitness of the swarm is:","%e"%std)
#将结果进行绘图
fig=plt.figure(figsize=(12, 10), dpi=300)
plt.title('The change of best fitness',fontdict='weight':'normal','size': 30)
x=range(1,101,1)
plt.plot(x,his_bestfit,color="red",label="GWO",linewidth=3.0, linestyle="-")
plt.tick_params(labelsize=25)
plt.xlim(0,101)
plt.yscale("log")
plt.xlabel("Epoch",fontdict='weight':'normal','size': 30)
plt.ylabel("Fitness value",fontdict='weight':'normal','size': 30)
plt.xticks(range(0,101,10))
plt.legend(loc="upper right",prop='size':20)
plt.savefig("GWO.png")
plt.show()
图中横轴为迭代次数,纵轴为最优适应度值。
参考源码
以上是关于优化算法的主要内容,如果未能解决你的问题,请参考以下文章
优化算法蚱蜢优化算法(GOA)含Matlab源码 1070期
优化算法差分松鼠搜索优化算法(DSSA)含Matlab源码 1330期