Tensorflow学习总结二

Tensorflow进阶——优化神经网络参数

1、优化神经网络模型
神经元模型: 用数学公式表示为:????(∑????*????+ ????),f 为**函数。神经网络是以神经元为基本单元构成的。
**函数引入非线性**因素,提高模型的表达力。 常用的**函数有 relu、sigmoid、tanh 等,在 Tensorflow 中,分别用 tf.nn.relu()、tf.nn.sigmoid()、 tf.nn.tanh()表示
Tensorflow学习总结二
Tensorflow学习总结二

Tensorflow学习总结二
:sigmoid函数在横坐标较大处的导数近乎为0,这就可能导致收敛速度特别慢等问题,同时它在坐标原点附件导数很大,这也会为训练制造麻烦,在训练的过程中,relu能更快的得到预测模型,有时选用tanh会有奇效。

神经网络的复杂度:可用神经网络的层数和神经网络中待优化参数个数表示
神经网路的层数:一般不计入输入层,层数 = n 个隐藏层 + 1 个输出层
神经网路待优化的参数:神经网络中所有参数 w 的个数 + 所有参数 b 的个数
损失函数(loss):用来表示预测值(y)与已知答案(y_)的差距,常用的损失函数有 均方误差、自定义和交叉熵 等。
在 Tensorflow 中,均方误差用:

loss_mse = tf.reduce_mean(tf.square(y_ - y))

还可根据问题的实际情况,定制合理的损失函数,如:在 Tensorflow 中,定义损失定义成分段函数:

#tf.where(tf.greater(y,y_),判断y是否比y_大,若是,执行COST(y-y_),若否,执行PROFIT(y_-y)
loss = tf.reduce_sum(tf.where(tf.greater(y,y_),COST(y-y_),PROFIT(y_-y)))

交叉熵(Cross Entropy):表示两个概率分布之间的距离。交叉熵越大,两个概率分布距离越远,两个概率分布越相异;交叉熵越小,两个概率分布距离越近,两个概率分布越相似。
交叉熵计算公式:????(????_ , ????) = −∑????_ ∗ ???????????? ????
用 Tensorflow 函数表示为 :

ce= -tf.reduce_mean(y_* tf.log(tf.clip_by_value(y, 1e-12, 1.0))) 

softmax 函数:将 n 分类的 n 个输出(y1,y2…yn)变为满足以下概率分布要求的函数。
∀???? ????(???? = ????) ∈ [????, ????] 且 ∑ ????????(???? = ????) = ????
softmax 函数表示为:
Tensorflow学习总结二
softmax 函数应用:在 n 分类中,模型会有 n 个输出,即 y1,y2…yn,其中 yi 表示第 i 种情况出现的可能性大小。将 n 个输出经过softmax函数,可得到符合概率分布的分类结果。在 Tensorflow 中,一般让模型的输出经sofemax 函数,以获得输出分类的概率分布,再与标准答案对比,求出交叉熵,得到损失函数,用如下函数实现:

ce = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
cem = tf.reduce_mean(ce)

2、优化学习率
学习率 learning_rate:表示了每次参数更新的幅度大小。学习率过大,会导致待优化的参数在最小值附近波动,不收敛;学习率过小,会导致待优化的参数收敛缓慢。在训练过程中,参数的更新向着损失函数梯度下降的方向。
学习率的设置
指数衰减学习率:学习率随着训练轮数变化而动态更新,用 Tensorflow 的函数表示为:

global_step = tf.Variable(0, trainable=False)
learning_rate=tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,LEARNING_RATE_STEP,LEARNING_RATE_DECAY,staircase=True/False)

其中,
LEARNING_RATE_BASE 为学习率初值,
LEARNING_RATE_DECAY 为学习率衰减率,
global_step 记录了当前训练轮数,为不可训练型参数。
学习率 learning_rate 更新频率为输入数据集总样本数除以每次喂入样本数。若 staircase 设置为 True 时,表示 global_step/learning rate step 取整数,学习率阶梯型衰减;若 staircase 设置为 false 时,学习率会是一条平滑下降的曲线。

如使用指数衰减学习率进行训练。其中,学习率初值设置为 0.1,学习率衰减率设置为 0.99,BATCH_SIZE 设置为 1。 代码如下:

#coding:utf-8
#设损失函数 loss = (w+1)^2,令w初值为常数10,反向传播就是求最优w,即求最小loss对应的w值
#使用指数衰减的学习率,在迭代初期得到较高的下降速度,可以再较小的训练轮数下更有收敛度

import tensorflow as tf

LEARNING_RATE_BASE = 0.1  #最初学习率
LEARNING_RATE_DECAY = 0.99   #学习率衰减率
LEARNING_RATE_STEP = 1  #喂入多少轮BATCH_SIZE后开始更新学习率,一般设为:总样本数/BATCH_SIZE

#运行了几轮BATCH_SIZE 的计数器,初值为0,设为不被训练
global_step = tf.Variable(0,trainable=False)
#定义指数下降学习率
learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,LEARNING_RATE_STEP,
                                           LEARNING_RATE_DECAY,staircase=True)
#定义待优化参数,初值为5
w = tf.Variable(tf.constant(5,dtype=tf.float32))
#定义损失函数
loss = tf.square(w+1)
#定义反向传播方法
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step=global_step)

#生成会话,训练40轮
with tf.Session() as sess:
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    for i in range(40):
        sess.run(train_step)
        learning_rate_val = sess.run(learning_rate)
        global_step_val = sess.run(global_step)
        w_val = sess.run(w)
        loss_val = sess.run(loss)
        print("After %s steps: global_step is %f, w is %f,learning rate is %f,"
              "loss is %f"%(i,global_step_val,w_val,learning_rate_val,loss_val))

滑动平均:记录了一段时间内模型中所有参数 w 和 b 各自的平均值。利用滑动平均值可以增强模型的泛化能力。
滑动平均值(影子)计算公式:
影子 = 衰减率 * 影子 +(1 - 衰减率)* 参数

其中,衰减率 = ???????????? {????????????????????????????????????????????????????????????????????????,????+轮数????????+轮数},
影子初值=参数初值 ,用 Tesnsorflow 函数表示为:

ema=tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)  
# MOVING_AVERAGE_DECAY 表示滑动平均衰减率,一般会赋接近 1 的值
#global_step 表示当前训练了多少轮。 

ema_op = ema.apply(tf.trainable_variables()) 
# ema.apply()函数实现对括号内参数求滑动平均
# tf.trainable_variables()函数实现把所有待训练参数汇总为列表。 

with tf.control_dependencies([train_step, ema_op]): 
      train_op = tf.no_op(name='train') 
#该函数实现将滑动平均和训练过程同步运行。 查看模型中参数的平均值,可以用 ema.average()函数。 

将 MOVING_AVERAGE_DECAY 设置为 0.99,参数 w1 设置为 0,w1 的滑动平均值设置为 0。开始时,轮数 global_step 设置为 0,参数 w1 更新为 1,则 w1 的滑动平均值为:
w1 滑动平均值=min(0.99,1/10)*0+(1– min(0.99,1/10)*1 = 0.9
当轮数 global_step 设置为 100 时,参数 w1 更新为 10,以下代码 global_step 保持为 100,每次执行滑动平均操作影子值更新,则滑动平均值变为:
w1滑动平均值=min(0.99,101/110)*0.9+(1–min(0.99,101/110)*10=0.826+0.818=1.644
再次运行,参数 w1 更新为 1.644,则滑动平均值变为:
w1 滑动平均值=min(0.99,101/110)*1.644+(1– min(0.99,101/110)*10 = 2.328
代码如下:

#coding:utf-8
import tensorflow as tf

#1、定义变量及滑动平均类
#定义一个32位浮点变量,初始值0.0,这个代码就是不断更新w1参数
w1 = tf.Variable(0,dtype=tf.float32)
#定义num_updates(NN的迭代轮数),初始值为0,不可被训练
global_step = tf.Variable(0,trainable=False)
#实例化滑动平均类,给删减率为0.99,当前轮数global_step
MOVING_AVERAGE_DECAY = 0.99
ema = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY,global_step)
#ema.apply后的括号里的更新列表,每次运行sess。run(ema_op)时,对更新列表中的元素求滑动平均值)
#在实际应用中会使用tf.trainable_Variables()自动将所有待训练的参数汇总为列表
ema_op = ema.apply(tf.trainable_variables())

#2、查看不同迭代中变量取值的变化
with tf.Session() as sess:
    #初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    #当前参数w1与w1的滑动平均值
    print(sess.run([w1,ema.average(w1)]))
    #参数w1的值赋为1
    sess.run(tf.assign(w1,1))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    #更新step和w1的值,模拟100轮迭代后,参数w1变为10
    sess.run(tf.assign(global_step,100))
    sess.run(tf.assign(w1,10))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    #每次sess。run会更新一次w1的滑动平均
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))
    sess.run(ema_op)
    print(sess.run([w1,ema.average(w1)]))

声明:本博客为学习《人工智能实践:Tensorflow笔记》:
https://www.icourse163.org/learn/PKU-1002536002#/learn/content
后总结,非常感谢曹健老师教授,转载请说明出处。