TensorFlow相关学习

0、网络上关于global_step基本作用

global_step在滑动平均、优化器、指数衰减学习率等方面都有用到,这个变量的实际意义非常好理解:代表全局步数,比如在多少步该进行什么操作,现在神经网络训练到多少轮等等,类似于一个钟表。

1、优化器Optimizer

主要讲一些常用的:
- Optimizer
- GradientDescentOptimizer
- AdagradOptimizer
- AdagradDAOptimizer
- MomentumOptimizer
- AdamOptimizer
- FtrlOptimizer
- RMSProOptimizer

2、常用的Optimizer

①class tf.train.Optimizer

优化器(optimizers)类的基类。这个类定义了在训练模型的时候添加一个操作的API。你基本上不会直接使用这个类,但是你会用到他的子类比如GradientDescentOptimizer, AdagradOptimizer, MomentumOptimizer.等等这些。

②class tf.train.GradientDescentOptimizer

作用: 这个类是实现梯度下降算法的优化器。
tf.train.GradientDescentOptimizer.init(learning_rate,use_locking=False,name=’GradientDescent’)

参数:
- 学习率:A Tensor or a floating point value. The learning rate to use.
- use_locking:If True use locks for update operation.s
- name:Optional name prefix for the optionals created when applying gradients.默认为“GradientDescent”.
compute_gradients(loss,var_list=None,gate_gradients=GATE_OP,aggregation_method=None,colocate_gradients_with_ops=False,grad_loss=None)
+ 作用:对于在变量列表(var_list)中的变量计算对于损失函数的梯度,这个函数返回一个(梯度,变量)对的列表,其中梯度就是相对应变量的梯度了。这是minimize()函数的第一个部分.
+ 参数:
+ loss:A Tensor containing the value to minimize.
+ var_list: 默认是在GraphKey.TRAINABLE_VARIABLES.

3、tf.get_variable()与tf.Variable()

先介绍相关函数定义

tf.Variable(initial_value=None, trainable=True, collections=None, validate_shape=True, caching_device=None, name=None, variable_def=None, dtype=None, expected_shape=None, import_scope=None)
tf.get_variable(name, shape=None, dtype=None, initializer=None, regularizer=None, trainable=True, collections=None, caching_device=None, partitioner=None, validate_shape=True, custom_getter=None)

查到关于两者的介绍,在Tensorflow:实战Google深度学习框架(第二版)的108页变量管理有介绍:用于创建变量时两者等效。两者最大的区别在于:对于tf.Variable函数,变量名称是一个可选参数,通过name=”V”的形式给出。但是对于tf.get_variable函数,变量名称是一个必填的参数。

tf.get_variable会根据这个名字去创建或获取变量。一般tf.get_variable首先会创建一个名字(例如v)的参数,如果创建失败(比如已有同名的参数),那么程序就会报错。

其他地方看到的一句话也不错:

  • 基于这两个函数的特性,当我们需要共享变量的时候,需要使用tf.get_variable()。在其他情况下,这两个的用法是一样的.
    import tensorflow as tf

    with tf.variable_scope("scope1"):
        w1 = tf.get_variable("w1", shape=[])
        w2 = tf.Variable(0.0, name="w2")
    with tf.variable_scope("scope1", reuse=True):
        w1_p = tf.get_variable("w1", shape=[])
        w2_p = tf.Variable(1.0, name="w2")

    print(w1 is w1_p, w2 is w2_p)
    #输出
    #True  False
  • 看到这,就可以明白官网上说的参数复用的真面目了。由于tf.Variable() 每次都在创建新对象,所有reuse=True 和它并没有什么关系。对于get_variable(),来说,如果已经创建的变量对象,就把那个对象返回,如果没有创建变量对象的话,就创建一个新的。

4、Tensorflow -tf.shape(a)和a.get_shape()比较

  • 相同点:都可以得到tensor a 的尺寸
  • 不同点:tf.shape()中a的数据的类型可以是tensor、list、array
        而a.get_shape()中a的数据类型只能是tensor,且返回的是一个元祖(tuple)
        
import tensorflow as tf  
import numpy as np  

x=tf.constant([[1,2,3],[4,5,6]]  
y=[[1,2,3],[4,5,6]]  
z=np.arange(24).reshape([2,3,4]))  

sess=tf.Session()  
# tf.shape()  
x_shape=tf.shape(x)                    #  x_shape 是一个tensor  
y_shape=tf.shape(y)                    #  <tf.Tensor 'Shape_2:0' shape=(2,) dtype=int32>  
z_shape=tf.shape(z)                    #  <tf.Tensor 'Shape_5:0' shape=(3,) dtype=int32>  
print sess.run(x_shape)              # 结果:[2 3]  
print sess.run(y_shape)              # 结果:[2 3]  
print sess.run(z_shape)              # 结果:[2 3 4]  


#a.get_shape()  
x_shape=x.get_shape()  # 返回的是TensorShape([Dimension(2), Dimension(3)]),不能使用 sess.run() 因为返回的不是tensor 或string,而是元组  
x_shape=x.get_shape().as_list()  # 可以使用 as_list()得到具体的尺寸,x_shape=[2 3]  
y_shape=y.get_shape()  # AttributeError: 'list' object has no attribute 'get_shape'  
z_shape=z.get_shape()  # AttributeError: 'numpy.ndarray' object has no attribute 'get_shape'



实例2:

import tensorflow as tf
import numpy as np

a = tf.Variable([[1,2,3]])

b = tf.reduce_sum(a,reduction_indices=[0])#值为[1,2,3]
s = tf.shape(b)[0]
init = tf.global_variables_initializer()

with tf.Session() as sess:
    sess.run(init)

    print(sess.run(a))#输出[[1 2 3]]
    print(type(sess.run(a))) #输出<class numpy.ndarray>
    print(sess.run(b))#输出[1 2 3]
    print(sess.run(s))#输出[3]
    print(s) #输出Tnesor("strided_slice:0")
    print(b.get_shape())#输出(3,)

m = np.array([1,2,3])
print(m)  #输出[1 2 3]
print(m.shape) #输出(3,)

5、神经网络优化

5.1 学习率的设置

训练过程中,学习率既不能过大,也不能过小。为了解决学习率的问题,TensorFlow提供了一种更加灵活的学习率设置方法——指数衰减法。
tf.train.exponential_decay(learning_rate,global_step,decay_steps,decay_rate,staircase=False,name=None)
函数实现了这种需求。通过该函数,可以先用比较大的学习率快速得到一个比较优的解,然后随着迭代的继续逐步减小学习率,使得模型在训练期更加稳定。函数实现以下代码功能:

decayed_learning_rate = \
   learning_rate * decay_rate ^ (global_step / decay_steps)

其中decayed_learning_rate为每一轮优化时使用的学习率,learning_rate为事先设定的初始学习率,decay_rate为衰减系数,decay_steps为衰减速度。
函数中的stair_case默认为False,为标准指数型衰减,下图中红色曲线。若为True,则global_step/decay_steps会被转化成整数,使得学习率成为一个阶梯函数,图中蓝色曲线。
image

5.2 滑动平均模型

滑动平均模型是一个可以使模型在测试数据上更健壮(robust)的方法。在采用随机梯度下降算法训练神经网络时,使用滑动平均模型在很多应用中都可以在一定程度提高最终模型在测试数据上的表现。

在tensorflow中提供了tf.train.ExponentialMovingAverage 来实现滑动平均模型,在采用随机梯度下降算法训练神经网络时,使用其可以提高模型在测试数据上的健壮性(robustness)。

TensorFlow下的 tf.train.ExponentialMovingAverage 需要提供一个衰减率decay。该衰减率用于控制模型更新的速度。该衰减率用于控制模型更新的速度,ExponentialMovingAverage 对每一个待更新的变量(variable)都会维护一个影子变量(shadow variable)。影子变量的初始值就是这个变量的初始值,每次运行变量更新时,影子变量的值会更新为:

shadow\_variable = decay \times shadow\_variable+(1-decay)\times variable

其中shadow_variabe为影子变量,variable为待更新的变量,decay为衰减率。decay决定了模型更新的速度,decay越大模型越趋于稳定。实际运用中,decay 一般会设置为十分接近 1 的常数(0.999或0.9999)。为了使得模型在训练的初始阶段更新得更快,ExponentialMovingAverage 还提供了 num_updates 参数来动态设置 decay 的大小:

decay =\min\{decay,\frac{1+num\_updates}{10+num\_updates}\}

插入一段书中的代码解释该函数的使用:

import tensorflow as tf

v1 = tf.Variable(0, dtype=tf.float32) #初始化v1变量
step = tf.Variable(0, trainable=False) #初始化step为0
ema = tf.train.ExponentialMovingAverage(0.99, step) #定义平滑类,设置参数以及控制衰减率的变量step=num_updates
#定义一个更新变量滑动平均的操作。这里需要给定一个列表,每次执行这个操作时
#这个列表中的变量都会被更新
maintain_averages_op = ema.apply([v1]) //定义更新变量平均操作

with tf.Session() as sess:

    # 初始化
    init_op = tf.global_variables_initializer()
    sess.run(init_op)
    #通过ema.average(v1)获取滑动平均之后变量的取值。在初始化之后变量v1的值和v1的滑动平均都为0
    print sess.run([v1, ema.average(v1)]) #输出[0.0,0.0]

    # 更新变量v1的值到5
    sess.run(tf.assign(v1, 5))
    #更新v1的滑动平均值。衰减率为min{0.99,(1+step)/(10+step)=0.1}=0.1,
    #所以v1的滑动平均会被更新为0.1*0+0.9*5=4.5
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)])  #输出[5.0,4.5]

    # 更新step和v1的取值
    sess.run(tf.assign(step, 10000))  
    sess.run(tf.assign(v1, 10))
    #更新v1的滑动平均值。衰减率为min{0.99,(1+step)/(10+step)≈0.999}=0.99,
    #所以v1的滑动平均会被更新为0.99*4.5+0.01*10=4.555.
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)])      #输出[10.0,4.5549998] 

    # 更新一次v1的滑动平均值=0.99*4.555+0.01*10=4.60945
    sess.run(maintain_averages_op)
    print sess.run([v1, ema.average(v1)])    #输出[10.0,4.6094499]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值