前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Tensorflow中 tf.train.exponential_decay() 等实现学习率衰减

Tensorflow中 tf.train.exponential_decay() 等实现学习率衰减

作者头像
用户7886150
修改2021-01-05 10:26:53
1.6K0
修改2021-01-05 10:26:53
举报
文章被收录于专栏:bit哲学院

参考链接: Python中的numpy.float_power

学习率衰减(learning rate decay)  在训练神经网络时,使用学习率控制参数的更新速度.学习率较小时,会大大降低参数的更新速度;学习率较大时,会使搜索过程中发生震荡,导致参数在极优值附近徘徊.  为此,在训练过程中引入学习率衰减,使学习率随着训练的进行逐渐衰减. 

TensorFlow中实现的学习率衰减方法: 

tf.train.piecewise_constant 分段常数衰减tf.train.inverse_time_decay 反时限衰减tf.train.polynomial_decay 多项式衰减tf.train.exponential_decay 指数衰减tf.train.natural_exp_decay 自然指数衰减tf.train.cosine_decay 余弦衰减tf.train.linear_cosine_decay 线性余弦衰减tf.train.noisy_linear_cosine_decay 噪声线性余弦衰减 

函数返回衰减的学习率. 

先讲单个函数的使用效果,最后演示如何将其用在实际模型中。 

首先是使用效果: 

分段常数衰减:tf.train.piecewise_constant() 指定间隔的分段常数.  参数: 

x:0-D标量Tensor.boundaries:边界,tensor或list.values:指定定义区间的值.name:操作的名称,默认为PiecewiseConstant.

分段常数衰减就是在定义好的区间上,分别设置不同的常数值,作为学习率的初始值和后续衰减的取值. 

#!/usr/bin/python

# coding:utf-8

# piecewise_constant 阶梯式下降法

import matplotlib.pyplot as plt

import tensorflow as tf

global_step = tf.Variable(0, name='global_step', trainable=False)

boundaries = [10, 20, 30]

learing_rates = [0.1, 0.07, 0.025, 0.0125]

y = []

N = 40

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        learing_rate = tf.train.piecewise_constant(global_step, boundaries=boundaries, values=learing_rates)

        lr = sess.run([learing_rate])

        y.append(lr[0])

x = range(N)

plt.plot(x, y, 'r-', linewidth=2)

plt.title('piecewise_constant')

plt.show()

指数衰减:tf.train.exponential_decay() 应用指数衰减的学习率.  指数衰减是最常用的衰减方法.  参数: 

learning_rate:初始学习率.global_step:用于衰减计算的全局步数,非负.用于逐步计算衰减指数.decay_steps:衰减步数,必须是正值.决定衰减周期.decay_rate:衰减率.staircase:若为True,则以不连续的间隔衰减学习速率即阶梯型衰减(就是在一段时间内或相同的eproch内保持相同的学习率);若为False,则是标准指数型衰减.name:操作的名称,默认为ExponentialDecay.(可选项)

指数衰减的学习速率计算公式为: 

decayed_learning_rate = learning_rate * decay_rate ^ (global_step / decay_steps)   优点:简单直接,收敛速度快. 

直观解释:假设给定初始学习率learning_rate为0.1,学习率衰减率为0.1,decay_steps为10000。  则随着迭代次数从1到10000,当前的学习率decayed_learning_rate慢慢的从0.1降低为0.1*0.1=0.01,  当迭代次数到20000,当前的学习率慢慢的从0.01降低为0.1*0.1^2=0.001,以此类推。  也就是说每10000次迭代,学习率衰减为前10000次的十分之一,该衰减是连续的,这是在staircase为False的情况下。 

如果staircase为True,则global_step / decay_steps始终取整数,也就是说衰减是突变的,每decay_steps次变化一次,变化曲线是阶梯状。   

示例,阶梯型衰减与指数型衰减对比:   

#!/usr/bin/python

# coding:utf-8

import matplotlib.pyplot as plt

import tensorflow as tf

global_step = tf.Variable(0, name='global_step', trainable=False)

y = []

z = []

N = 200

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        # 阶梯型衰减

        learing_rate1 = tf.train.exponential_decay(

            learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=True)

        # 标准指数型衰减

        learing_rate2 = tf.train.exponential_decay(

            learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)

        lr1 = sess.run([learing_rate1])

        lr2 = sess.run([learing_rate2])

        y.append(lr1[0])

        z.append(lr2[0])

x = range(N)

fig = plt.figure()

ax = fig.add_subplot(111)

ax.set_ylim([0, 0.55])

plt.plot(x, y, 'r-', linewidth=2)

plt.plot(x, z, 'g-', linewidth=2)

plt.title('exponential_decay')

ax.set_xlabel('step')

ax.set_ylabel('learing rate')

plt.show() 

如图,红色:阶梯型;绿色:指数型:  

自然指数衰减:tf.train.natural_exp_decay()  应用自然指数衰减的学习率.  参数: 

learning_rate:初始学习率.global_step:用于衰减计算的全局步数,非负.decay_steps:衰减步数.decay_rate:衰减率.staircase:若为True,则是离散的阶梯型衰减(就是在一段时间内或相同的eproch内保持相同的学习率);若为False,则是标准型衰减.name: 操作的名称,默认为ExponentialTimeDecay.

natural_exp_decay 和 exponential_decay 形式近似,natural_exp_decay的底数是e.自然指数衰减比指数衰减要快的多,一般用于较快收敛,容易训练的网络.  自然指数衰减的学习率计算公式为: 

decayed_learning_rate = learning_rate * exp(-decay_rate * global_step) 示例,指数衰减与自然指数衰减的阶梯型与指数型: 

#!/usr/bin/python

# coding:utf-8

import matplotlib.pyplot as plt

import tensorflow as tf

global_step = tf.Variable(0, name='global_step', trainable=False)

y = []

z = []

w = []

N = 200

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        # 阶梯型衰减

        learing_rate1 = tf.train.natural_exp_decay(

            learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=True)

        # 标准指数型衰减

        learing_rate2 = tf.train.natural_exp_decay(

            learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)

        # 指数衰减

        learing_rate3 = tf.train.exponential_decay(

            learning_rate=0.5, global_step=global_step, decay_steps=10, decay_rate=0.9, staircase=False)

        lr1 = sess.run([learing_rate1])

        lr2 = sess.run([learing_rate2])

        lr3 = sess.run([learing_rate3])

        y.append(lr1[0])

        z.append(lr2[0])

        w.append(lr3[0])

x = range(N)

fig = plt.figure()

ax = fig.add_subplot(111)

ax.set_ylim([0, 0.55])

plt.plot(x, y, 'r-', linewidth=2)

plt.plot(x, z, 'g-', linewidth=2)

plt.plot(x, w, 'b-', linewidth=2)

plt.title('natural_exp_decay')

ax.set_xlabel('step')

ax.set_ylabel('learing rate')

plt.show() 

如图,红色:阶梯型;绿色:指数型;蓝色指数型衰减: 

多项式衰减:tf.train.polynomial_decay() 应用多项式衰减的学习率.  参数: 

learning_rate:初始学习率.global_step:用于衰减计算的全局步数,非负.decay_steps:衰减步数,必须是正值.end_learning_rate:最低的最终学习率.power:多项式的幂,默认为1.0(线性).cycle:学习率下降后是否重新上升.name:操作的名称,默认为PolynomialDecay。

函数使用多项式衰减,以给定的decay_steps将初始学习率(learning_rate)衰减至指定的学习率(end_learning_rate). 

多项式衰减的学习率计算公式为: 

global_step = min(global_step,decay_steps) decayed_learning_rate = (learning_rate-end_learning_rate)*(1-global_step/decay_steps)^ (power)+end_learning_rate 

参数cycle决定学习率是否在下降后重新上升.若cycle为True,则学习率下降后重新上升;使用decay_steps的倍数,取第一个大于global_steps的结果. 

decay_steps = decay_steps*ceil(global_step/decay_steps) decayed_learning_rate = (learning_rate-end_learning_rate)*(1-global_step/decay_steps)^ (power)+end_learning_rate 

参数cycle目的:防止神经网络训练后期学习率过小导致网络一直在某个局部最小值中振荡;这样,通过增大学习率可以跳出局部极小值. 

示例,学习率下降后是否重新上升对比: 

#!/usr/bin/python

# coding:utf-8

# 学习率下降后是否重新上升

import matplotlib.pyplot as plt

import tensorflow as tf

y = []

z = []

N = 200

global_step = tf.Variable(0, name='global_step', trainable=False)

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        # cycle=False

        learing_rate1 = tf.train.polynomial_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=50,

            end_learning_rate=0.01, power=0.5, cycle=False)

        # cycle=True

        learing_rate2 = tf.train.polynomial_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=50,

            end_learning_rate=0.01, power=0.5, cycle=True)

        lr1 = sess.run([learing_rate1])

        lr2 = sess.run([learing_rate2])

        y.append(lr1[0])

        z.append(lr2[0])

x = range(N)

fig = plt.figure()

ax = fig.add_subplot(111)

plt.plot(x, z, 'g-', linewidth=2)

plt.plot(x, y, 'r--', linewidth=2)

plt.title('polynomial_decay')

ax.set_xlabel('step')

ax.set_ylabel('learing rate')

plt.show() 

如图,红色:下降后不再上升;绿色:下降后重新上升:  

余弦衰减:tf.train.cosine_decay() 将余弦衰减应用于学习率  参数: 

learning_rate:标初始学习率.global_step:用于衰减计算的全局步数.decay_steps:衰减步数.alpha:最小学习率(learning_rate的部分)。name:操作的名称,默认为CosineDecay.

根据论文SGDR: Stochastic Gradient Descent with Warm Restarts提出. 

余弦衰减的学习率计算公式为: 

global_step = min(global_step, decay_steps) cosine_decay = 0.5 * (1 + cos(pi * global_step / decay_steps)) decayed = (1 - alpha) * cosine_decay + alpha decayed_learning_rate = learning_rate * decayed 

线性余弦衰减:tf.train.linear_cosine_decay() 将线性余弦衰减应用于学习率.  参数: 

learning_rate:标初始学习率.global_step:用于衰减计算的全局步数.decay_steps:衰减步数。num_periods:衰减余弦部分的周期数.alpha:见计算.beta:见计算.name:操作的名称,默认为LinearCosineDecay。

根据论文Neural Optimizer Search with Reinforcement Learning提出. 

线性余弦衰减的学习率计算公式为: 

global_step=min(global_step,decay_steps) linear_decay=(decay_steps-global_step)/decay_steps) cosine_decay = 0.5*(1+cos(pi*2*num_periods*global_step/decay_steps)) decayed=(alpha+linear_decay)*cosine_decay+beta decayed_learning_rate=learning_rate*decayed 

噪声线性余弦衰减:tf.train.noisy_linear_cosine_decay() 将噪声线性余弦衰减应用于学习率.  参数: 

learning_rate:标初始学习率.global_step:用于衰减计算的全局步数.decay_steps:衰减步数.initial_variance:噪声的初始方差.variance_decay:衰减噪声的方差.num_periods:衰减余弦部分的周期数.alpha:见计算.beta:见计算.name:操作的名称,默认为NoisyLinearCosineDecay.

根据论文Neural Optimizer Search with Reinforcement Learning提出.在衰减过程中加入了噪声,一定程度上增加了线性余弦衰减的随机性和可能性. 

噪声线性余弦衰减的学习率计算公式为: 

global_step=min(global_step,decay_steps) linear_decay=(decay_steps-global_step)/decay_steps) cosine_decay=0.5*(1+cos(pi*2*num_periods*global_step/decay_steps)) decayed=(alpha+linear_decay+eps_t)*cosine_decay+beta decayed_learning_rate =learning_rate*decayed 示例,线性余弦衰减与噪声线性余弦衰减:   

#!/usr/bin/python

# coding:utf-8

import matplotlib.pyplot as plt

import tensorflow as tf

y = []

z = []

w = []

N = 200

global_step = tf.Variable(0, name='global_step', trainable=False)

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        # 余弦衰减

        learing_rate1 = tf.train.cosine_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=50,

            alpha=0.5)

        # 线性余弦衰减

        learing_rate2 = tf.train.linear_cosine_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=50,

            num_periods=0.2, alpha=0.5, beta=0.2)

        # 噪声线性余弦衰减

        learing_rate3 = tf.train.noisy_linear_cosine_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=50,

            initial_variance=0.01, variance_decay=0.1, num_periods=0.2, alpha=0.5, beta=0.2)

        lr1 = sess.run([learing_rate1])

        lr2 = sess.run([learing_rate2])

        lr3 = sess.run([learing_rate3])

        y.append(lr1[0])

        z.append(lr2[0])

        w.append(lr3[0])

x = range(N)

fig = plt.figure()

ax = fig.add_subplot(111)

plt.plot(x, z, 'b-', linewidth=2)

plt.plot(x, y, 'r-', linewidth=2)

plt.plot(x, w, 'g-', linewidth=2)

plt.title('cosine_decay')

ax.set_xlabel('step')

ax.set_ylabel('learing rate')

plt.show() 

如图,红色:余弦衰减;蓝色:线性余弦衰减;绿色:噪声线性余弦衰减;  

反时限衰减:tf.train.inverse_time_decay() 将反时限衰减应用到初始学习率.  参数: 

learning_rate:初始学习率.global_step:用于衰减计算的全局步数.decay_steps:衰减步数.decay_rate:衰减率.staircase:是否应用离散阶梯型衰减.(否则为连续型)name:操作的名称,默认为InverseTimeDecay.

该函数应用反向衰减函数提供初始学习速率.利用global_step来计算衰减的学习速率.计算公式为: 

decayed_learning_rate =learning_rate/(1+decay_rate* global_step/decay_step) 若staircase为True时: 

decayed_learning_rate =learning_rate/(1+decay_rate*floor(global_step/decay_step)) 示例,反时限衰减的阶梯型衰减与连续型对比:   

#!/usr/bin/python

# coding:utf-8

import matplotlib.pyplot as plt

import tensorflow as tf

y = []

z = []

N = 200

global_step = tf.Variable(0, name='global_step', trainable=False)

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for global_step in range(N):

        # 阶梯型衰减

        learing_rate1 = tf.train.inverse_time_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=20,

            decay_rate=0.2, staircase=True)

        # 连续型衰减

        learing_rate2 = tf.train.inverse_time_decay(

            learning_rate=0.1, global_step=global_step, decay_steps=20,

            decay_rate=0.2, staircase=False)

        lr1 = sess.run([learing_rate1])

        lr2 = sess.run([learing_rate2])

        y.append(lr1[0])

        z.append(lr2[0])

x = range(N)

fig = plt.figure()

ax = fig.add_subplot(111)

plt.plot(x, z, 'r-', linewidth=2)

plt.plot(x, y, 'g-', linewidth=2)

plt.title('inverse_time_decay')

ax.set_xlabel('step')

ax.set_ylabel('learing rate')

plt.show() 

如图,蓝色:阶梯型;红色:连续型:  

----------------------------------------------------------------------------------------------------------------------------------  

以上是单个的使用效果,但是在实际模型中这些函数并不是这么使用的,以下使用两个方法,简述如何在模型中使用学习率衰减! 

----------------------------------------------------------------------------------------------------------------------------------  

首先第一个例子: 

例如 

tf.train.exponential_decay(initial_learning_rate, global_step=global_step, decay_steps=1000, decay_rate=0.9)表示没经过1000次的迭代,学习率变为原来的0.9。 

增大批次处理样本的数量也可以起到退化学习率的作用。 

下面我们写了一个例子,每迭代10次,则较小为原来的0.5,代码如下: 

import tensorflow as tf

import numpy as np

global_step = tf.Variable(0, trainable=False)

initial_learning_rate = 0.1

learning_rate = tf.train.exponential_decay(initial_learning_rate,

                                           global_step=global_step,

                                           decay_steps=10,

                                           decay_rate=0.5)

opt = tf.train.GradientDescentOptimizer(learning_rate)

add_global = global_step.assign_add(1)

with tf.Session() as sess:

    tf.global_variables_initializer().run()

    print(sess.run(learning_rate))

    for i in range(50):

        g, rate = sess.run([add_global, learning_rate])

        print(g, rate) 

在这个代码里面使用add_global = global_step.assign_add(1)来实现全局迭代步数+1的更新; 

下面是程序的结果,我们发现每10次就变为原来的一半: 

下面在mnist数据集上使用该方法去测试,代码如下: 

import tensorflow as tf

import numpy as np

from tensorflow.examples.tutorials.mnist import input_data

import matplotlib.pyplot as plt

mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

tf.reset_default_graph()

x = tf.placeholder(tf.float32, [None, 784])

y = tf.placeholder(tf.float32, [None, 10])

w = tf.Variable(tf.random_normal([784, 10]))

b = tf.Variable(tf.zeros([10]))

pred = tf.matmul(x, w) + b

pred = tf.nn.softmax(pred)

cost = tf.reduce_mean(-tf.reduce_sum(y * tf.log(pred), reduction_indices=1))

global_step = tf.Variable(0, trainable=False)

initial_learning_rate = 0.1

learning_rate = tf.train.exponential_decay(initial_learning_rate,

                                           global_step=global_step,

                                           decay_steps=1000,

                                           decay_rate=0.9)

opt = tf.train.GradientDescentOptimizer(learning_rate)

add_global = global_step.assign_add(1)

optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost)

training_epochs = 50

batch_size = 100

display_step = 1

with tf.Session() as sess:

    sess.run(tf.global_variables_initializer())

    for epoch in range(training_epochs):

        avg_cost = 0

        total_batch = int(mnist.train.num_examples/batch_size)

        for i in range(total_batch):

            batch_xs, batch_ys = mnist.train.next_batch(batch_size)

            _, c, add, rate = sess.run([optimizer, cost, add_global, learning_rate], feed_dict={x:batch_xs, y:batch_ys})

            avg_cost += c / total_batch

        if (epoch + 1) % display_step == 0:

            print('epoch= ', epoch+1, ' cost= ', avg_cost, 'add_global=', add, 'rate=', rate)

    print('finished')

    correct_prediction = tf.equal(tf.argmax(pred, 1), tf.argmax(y, 1))

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

    print('accuracy: ', accuracy.eval({x:mnist.test.images, y:mnist.test.labels})) 

其次是第二个例子: 

# 下面设置学习率衰减,tf.train.inverse_time_decay是反时限衰减

    global_step = tf.Variable(0, trainable=False)

    learning_rate = tf.train.inverse_time_decay(LEARNING_RATE, global_step, 5000, 0.5)

    Opt_D = tf.train.AdamOptimizer(learning_rate).minimize(D_loss, var_list=D.var(), global_step=global_step)

    # 在上面的minimize中会实现global_step次数的加1.一次梯度下降中只需要加一次,之所以下面的就不需要再加了

    Opt_G = tf.train.AdamOptimizer(learning_rate).minimize(G_loss, var_list=G.var())

    # 如果不想用minimize这种方法,那么可以自己写add_global = global_step.assign_add(1)并计算更新 

在sess.run中获取详细的学习率的写法举例: 

[dloss, gloss, Mglobal, fakeimg, step, lr] = sess.run([D_loss, G_loss, M_global, fake_img, global_step, learning_rate], feed_dict={real_img: batch, z: z0})

相关例子的详细代码可以下载我注释相应的资源。 

参考:https://blog.csdn.net/akadiao/article/details/79560731 

          https://www.baidu.com/link?url=wlFfuGH8nDDaDfhuElvs2jdyR5keRCHVqjQlXybBcKg5GN9CzrKOIE1Hlepjdb3BtEdlHn8htQEPzqh2BA7D584Ex-gelV5KvFByK9DWp7C&wd=&eqid=f9b7355900003134000000055eaa9aa0 

          https://www.cnblogs.com/baby-lily/p/10962574.html

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档