Darknet中的学习率调整策略

Darknet中的学习率调整策略

本文首发于微信公众号【DeepDriving】,欢迎关注。

导语

Darknet是一个比较小众的开源深度学习框架,与目前主流的深度学习框架不同的是,该框架由C语言实现,对于新手来说有一定的学习难度。但是即便这样,也挡不住我们使用该框架的热情(也可能是迫不得已),因为大名鼎鼎的目标检测算法YOLO(从v1~v4)就是基于该框架实现的。

在这里插入图片描述

学习率是训练深度学习模型时设置的一个关键的超参数,其值直接决定了训练的模型是否收敛、收敛的快慢程度:如果学习率设置得过大,则可能导致模型无法收敛;设置得过小则会导致模型收敛得很慢,从而使得训练时间过长。下图形象地说明了学习率对模型训练过程的影响:图1学习率过大,导致模型无法收敛;图2学习率过小,导致训练耗时较长;图3先设置了一个合适的学习率,然后在训练过程中还会适当地减少学习率,使得模型可以很好地收敛到全局最优点。

在这里插入图片描述

学习率是训练模型之前就设置好的一个超参数,在训练过程中还会基于一定的策略进行调整。

Darknet中的几种学习率调整策略

Darknet中,神经网络的模型结构和训练时需要的一些超参数都是在一个.cfg文件中指定。学习率的调整策略则是在.cfg文件中通过policy=进行设置,在框架的代码中,则是由parser.cget_policy()函数对.cfg文件中设定的调整策略字符串进行解析以确定本次训练所采用的学习率调整策略。Darknet框架支持的几种学习率调整策略定义在一个名为learning_rate_policy的枚举类型中,其中每个成员代表的调整策略的具体含义解释如下:

  • CONSTANT: 恒定的学习率,学习率初始值在.cfg文件设置好后,训练过程中不会再做调整。

  • RANDOM: 也是恒定的学习率,但其值由下面的公式决定

    η t = η ∗ λ p o w e r \eta _{t} = \eta * \lambda ^{power} ηt=ηλpower

    其中, η \eta η为初始学习率; λ \lambda λ0~1之间的随机数;power是由.cfg文件中的power=设置的参数。

  • POLY: 训练过程中学习率调整方式由下面公式决定

    η t = η ∗ ( 1 − b a t c h _ n u m m a x _ b a t c h e s ) p o w e r \eta _{t} = \eta * (1 - \frac{batch\_num}{max\_batches})^{power} ηt=η(1max_batchesbatch_num)power

    其中, η \eta η为初始学习率;batch_num为当前的迭代次数;max_batches为最大的迭代次数,该参数由.cfg文件中的max_batches=指定;power是由.cfg文件中的power=设置的参数。当 η = 0.1 , m a x _ b a t c h e s = 10000 , p o w e r = 4 \eta=0.1,max\_batches=10000, power=4 η=0.1,max_batches=10000,power=4时,训练过程中学习率的调整过程曲线如下图所示:

    在这里插入图片描述

  • STEP:: 训练过程中学习率调整方式由下面公式决定

    η t = η ∗ s c a l e b a t c h _ n u m / s t e p \eta _{t} = \eta * scale^{batch\_num/step} ηt=ηscalebatch_num/step

    其中, η \eta η为初始学习率;batch_num为当前的迭代次数;scale是由.cfg文件中的scale=设置的参数;step是由.cfg文件中的step=设置的参数。当 η = 0.1 , s c a l e = 0.1 , s t e p = 50000 \eta=0.1,scale=0.1,step=50000 η=0.1scale=0.1,step=50000时,训练过程中学习率的调整过程曲线如下图所示:

    在这里插入图片描述

  • EXP: 训练过程中学习率调整方式由下面公式决定

    η t = η ∗ γ b a t c h _ n u m \eta _{t} = \eta * \gamma ^{batch\_num} ηt=ηγbatch_num

    其中, η \eta η为初始学习率;batch_num为当前的迭代次数; γ \gamma γ是由.cfg文件中的gamma=设置的参数。当 η = 0.1 , γ = 0.9999 \eta=0.1,\gamma=0.9999 η=0.1γ=0.9999时,训练过程中学习率的调整过程曲线如下图所示:

    在这里插入图片描述

  • SIG: 训练过程中学习率调整方式由下面公式决定

    η t = η ∗ 1 1 + e γ ∗ ( b a t c h _ n u m − s t e p ) ) \eta _{t} = \eta * \frac{1}{1+e^{\gamma * (batch\_num - step)}}) ηt=η1+eγ(batch_numstep)1)

    其中, η \eta η为初始学习率;batch_num为当前的迭代次数; γ \gamma γ是由.cfg文件中的gamma=设置的参数;step是由.cfg文件中的step=设置的参数。当 η = 0.1 , γ = 0.0001 , s t e p = 50000 \eta=0.1,\gamma=0.0001,step=50000 η=0.1γ=0.0001,step=50000时,训练过程中学习率的调整过程曲线如下图所示:

    在这里插入图片描述

  • STEPS:: 一种阶段性调整策略,可以设置多个阶段,当前迭代次数达到设定值时,学习率调整为

    η t = η ∗ s c a l e \eta _{t} = \eta * scale ηt=ηscale

    在官方的yolov3.cfg文件中,有如下内容:

    policy=steps
    steps=400000,450000
    scales=.1,.1
    

    意思是当迭代次数达到400000时,学习率乘以0.1;当迭代次数达到450000时,学习率再乘以0.1。学习率调整曲线如下图所示:

    在这里插入图片描述

学习率预热

在Darknet框架中,还可以通过.cfg文件设定一个burn_in参数。该参数用于在训练的前期,让学习率以一定的方式从零逐渐增大到指定的初始学习率,相当于是让学习率有一段时间的“热身(warm up)”过程,这样做的目的是避免训练初期由于初始学习率设置得过大导致训练过程出现震荡。这个阶段内,学习率的调整策略由下面的公式决定:

η t = η ∗ ( b a t c h _ n u m b u r n _ i n ) p o w e r \eta _{t} = \eta * (\frac{batch\_num}{burn\_in})^{power} ηt=η(burn_inbatch_num)power

η = 0.1 , b u r n _ i n = 1000 , p o w e r = 4 \eta=0.1,burn\_in=1000,power=4 η=0.1burn_in=1000,power=4时,预热阶段学习率的调整过程曲线如下图所示:

在这里插入图片描述

如何在Darknet中新增学习率调整策略

上文介绍了Darknet中的几种学习率调整策略,但是如果我们想用其他的策略应该怎么办呢?下面就以添加COSINE调整策略为例说明如何在Darknet中添加一种新的学习率调整策略。COSINE调整策略的公式如下

η t = 1 2 ∗ η ∗ ( 1 + c o s ( b a t c h _ n u m ∗ π m a x _ b a t c h e s ) ) \eta _{t} = \frac{1}{2} * \eta * (1 + cos(\frac{batch\_num * \pi}{max\_batches})) ηt=21η(1+cos(max_batchesbatch_numπ))

其中, η \eta η为初始学习率;batch_num为当前的迭代次数;max_batches为最大迭代次数。训练过程中学习率的调整过程曲线如下图所示:

在这里插入图片描述

添加COSINE调整策略的过程如下:

  1. darknet.h文件中,为枚举类型learning_rate_policy添加一个成员COSINE
typedef enum {
    CONSTANT, STEP, EXP, POLY, STEPS, SIG, RANDOM, COSINE
} learning_rate_policy;
  1. parser.c文件中的get_policy()函数中添加对COSINE调整策略的支持:
learning_rate_policy get_policy(char *s)
{
    if (strcmp(s, "random")==0) return RANDOM;
    if (strcmp(s, "poly")==0) return POLY;
    if (strcmp(s, "constant")==0) return CONSTANT;
    if (strcmp(s, "step")==0) return STEP;
    if (strcmp(s, "exp")==0) return EXP;
    if (strcmp(s, "sigmoid")==0) return SIG;
    if (strcmp(s, "steps")==0) return STEPS;
    if (strcmp(s, "cosine")==0) return COSINE;
    fprintf(stderr, "Couldn't find policy %s, going with constant\n", s);
    return CONSTANT;
}
  1. parser.c文件中的parse_net_options()函数中去解析.cfg文件设置的参数。由于COSINE调整策略所需的参数max_batches已经有解析接口了,所以这里不需要额外添加。

  2. network.c文件中的get_current_rate()函数中添加一个switch分支语句,实现COSINE调整策略:

case COSINE:
      return net.learning_rate * 0.5 * (1 + cos(batch_num *M_PI / net.max_batches));
  1. 重新编译Darknet工程。编译成功后只要在.cfg文件中设置policy=cosine,就可以使用COSINE学习率调整策略了。如果要添加其他的策略,参照以上方法也很容易就可以实现。

结语

学习率是训练深度学习模型过程中的一个很重要的超参数,可以通过多种方式进行调整。由于Darknet框架没有学习率调整策略的相关文档,要想知道具体细节只能通过剖析源代码才能了解每个参数的含义。本文详细介绍了Darknet框架中的学习率调整策略,通过公式和图形的方式阐述每种调整策略各个参数的意义和调整的过程,同时也介绍了添加新的调整策略的方法,希望对本文的读者有所帮助。

欢迎关注我的公众号【DeepDriving】,我会不定期分享计算机视觉、机器学习、深度学习、无人驾驶等领域的文章。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeepDriving

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值