TENSORFLOW:VARIABLES

匿名 (未验证) 提交于 2019-12-02 23:41:02

Variables

TensorFlow里的variable是表示你程序操作的持续共享的状态的最好的方式。

变量是通过tf.Variable类操作的。一个tf.Variable表示一个tensor的值是可以通过操作来改变的。和tf.Tensor不同,tf.Variable是存在于单次session.run调用的context之外的。

在内部,一个tf.Variable存储着一个持久的tensor,特定的操作允许你读取或者修改这个tensor的值。而且这些修改是跨session的。所以多个worker可以看到同样值的tf.Variable.

创建一个Variable


最好的创建一个variable的办法是通过调用tf.get_variable方法。这个方法需要你设定变量的名字。别人可以通过这个名字来访问这个variable。同时这个名字还会在checkpointing和exporting model的时候给变量的值命名。tf.get_variable同时也允许你重用之前定义的同名变量。这样让你在定义模型时重用一些layer。

通过tf.get_variable创建一个变量的时候,只要简单的提供名字和shape

 

上边的代码创建了一个名叫my_variable的变量,它有3个维度,shape是[1,2,3].这个值默认是tf.float32类型的. 它的初始值会被tf.glorot_uniform_initializer随机初始化。

你也可以选在调用tf.get_variable的时候指定类型和初始化函数,比如:

 

TensorFlow提供了很多好用的initializers。另外你可以用一个tensor来出初始化一个tf.Variable.比如:

 

如果是用tensor来初始化variable,你就不用在指定shape了,会用初始化的tensor的shape来初始化variable的shape。

变量集合

因为tensorflow程序的不同部分都会创建variable,有时候你想用单一的方式访问所有的变量。因此tensorflow提供了collection,它是一个命名的tensor或者其他对象的list,比如tf.Variable实例.

默认情况下,一个variable被放在了两个集合里:


如果你有一个variable,你不想训练它,你就把他加到tf.GraphKeys.LOCAL_VARIABLES列表里。

 

或者,你也可以通过指定tf.get_variable的参数trainable=False来达到同样的目的:

 

你也可以用你自己的集合,任意字符串都是有效的集合名。你不需要自己创建一个集合,只需要直接把一个变量(或者其他对象)加入到一个集合,调用时你只需要给出这个集合的名字:

 tf.add_to_collection("my_coolection_name",my_local)

获取你之前放入collection的变量或者其他对象的方法是:

 tf.get_collection("my_collection_name")

指定设备

就像其他的tensorflow的操作,你可以把变量放置到特定的设备上。比如下边的代码段创建了一个变量v,并把它放到第二个GPU上。

 

在分布式的情况下,把variable放在合适的设备上是非常重要的。如果不小心把变量放在了worker上,而不是parameter机器上。会非常明显的降低训练速度。最差的情况,让每个worker都没有意识到自己在自己独立的一份variable上训练。因此,我们提供了tf.train.replica_device_setter,它可以自动的把variable放到parameter server上。比如:

 

初始化变量

在你使用一个变量前,你需要初始化。如果你用一些底层的tensorflow API编程(也就是你自己创建graph和session),你必须自己初始化这些变量。高层的API,比如tf.contrib.slim,tf.estimator.Estimator和Keras会在你训练模型前自动的初始化变量。

明确的初始化变量值非常有用,当你load一个训练了一半的模型时,可以设置之前训练了一半的变量值。当你在分布式环境下可以给各个机器设置同样的随机初始值。

一次设置所有的可以训练的变量,在训练开始前,你可以调用tf.gloabl_variables_initializer().这个方法返回一个operation,它负责初始化所有的在tf.GraphKeys.GLOBAL_VARIABLES集合里的变量。运行这个operation,会初始化所有的变量。比如:

 sess.run(tf.global_variables_initializer()) #现在所有的变量都初始化了。

如果你需要自己初始化变量,你可以运行变量自己的initializer。比如:

 sess.run(my_variable.initializer)

你也可以通过下边的代码查看哪些变量还没有被初始化:

 print(sess.run(tf.report_uninitialized_variables()))

默认情况下,tf.global_variables_initializer是不指定变量初始化顺序的。因此如果一个变量的初始化值依赖于另一个变量的值,你可能会得到一个error。所以你最好在代码里,在所有的变量没有被初始化的时候,不要直接用一个variable的值,而使用它的initialized_value.比如:

 

使用变量


在tensorflow的graph里,使用variable就像使用tensor一样。

 

给变量赋一个值,可以使用方法assign,assign_add,和tf.Variable里的其他方法,比如:

 

绝大多数的tensorflow optimizer有专用的操作来高效的更新变量的值,依据像梯度下降这样的算法。tf.train.Optimizer的文档详细说了如何使用optimizer。

因为变量是可以更改的。所以有时知道变量的版本是很有用的。在某些操作后强制去重新读一个变量的值,你可以用tf.Variable.read_value。比如:

 

共享变量


TensorFlow有两种共享变量的方式:

通过代码传递variable对象非常清晰。但是有时候我们在写tensorflow的function的时候,用隐式变量比较方便。大多数tf.layer里的layers和所有的tf.metrics以及一些工具库都是用这种方式。

比如我们这里创建一个激活函数为relu的卷积层:

 

我们给变量起了weight和bias这样通用的名字。但是在一个深度卷积神经网络里,我们会创建很多卷积层。我们如果重复的调用这个funciton就会有问题。

 

因为期望的行为并不清晰,你到底是想创建新的变量还是重用老的变量。所以执行会失败。在不同变量域里就不会有这个歧义。下边的代码就会创建新的变量:

 

如果你想变量被共享。你有两种选择,你可以定义一个和之前同名的变量scope,并且把reuse参数设置为True:

 

你也可以用scope.reuse_variables()方法来触发一个重用:

 

因为用string来定义scope可能你觉得不安全,你也可以用已有的scope对象来初始化另一个scope:

 

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

原文:http://www.rethink.fun/index.php/2018/03/11/tensorflow4/

文章来源: https://blog.csdn.net/lcczzu/article/details/91457947
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!