Python 在TensorFlow中,tf.identity用于什么?
我在一些地方看到了Python 在TensorFlow中,tf.identity用于什么?,python,tensorflow,Python,Tensorflow,我在一些地方看到了tf.identity,比如官方的CIFAR-10教程和stackoverflow上的批量规范化实现,但我不明白为什么有必要这样做 它是用来干什么的?有人能给出一两个用例吗 一个建议的答案是,它可以用于CPU和GPU之间的传输。这我不清楚。问题的扩展基于:loss=tower\u loss(scope)位于GPU块下,这向我建议,在tower\u loss中定义的所有操作符都映射到GPU。然后,在tower\u loss的末尾,我们看到返回之前的total\u loss=tf.
tf.identity
,比如官方的CIFAR-10教程和stackoverflow上的批量规范化实现,但我不明白为什么有必要这样做
它是用来干什么的?有人能给出一两个用例吗
一个建议的答案是,它可以用于CPU和GPU之间的传输。这我不清楚。问题的扩展基于:
loss=tower\u loss(scope)
位于GPU块下,这向我建议,在tower\u loss
中定义的所有操作符都映射到GPU。然后,在tower\u loss
的末尾,我们看到返回之前的total\u loss=tf.identity(total\u loss)
。为什么?不在此处使用tf.identity
会有什么缺陷?tf.identity
在您希望在设备之间显式传输张量(例如,从GPU到CPU)时非常有用。
op将发送/接收节点添加到图形中,当输入和输出的设备不同时,这些节点会进行复制
默认行为是,当操作发生在不同的设备上时,会隐式添加send/recv节点,但您可以想象某些情况(尤其是在多线程/分布式设置中),在执行会话的一次过程中多次获取变量值可能会很有用。run
tf.identity
允许对何时应从源设备读取值进行更多控制。可能这个op更合适的名称是read
另外,请注意,在tf.Variable
的实现中,构造函数中添加了标识op,这确保对变量的所有访问只从源复制数据一次。如果变量存在于GPU上,但由多个CPU操作读取(或者相反),那么多个副本可能会很昂贵。如果需要,用户可以通过多次调用tf.identity
来更改行为
编辑:编辑问题后更新答案
此外,tf.identity
可以用作虚拟节点来更新对张量的引用。这对于各种控制流操作非常有用。在CIFAR案例中,我们希望强制执行指数移动平均值将在检索损失值之前更新相关变量。这可以通过以下方式实现:
with tf.control_dependencies([loss_averages_op]):
total_loss = tf.identity(total_loss)
在这里,
tf.identity
除了标记总损失
张量之外没有任何用处,在评估损失平均值
之后,我想我已经注意到了一个适用于我所看到的所有示例的用例。如果还有其他用例,请举例说明
用例:
假设您希望在每次计算特定变量时运行一个运算符。例如,假设您希望在每次计算变量y
时向x
添加一个变量。这似乎会奏效:
x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)
with tf.control_dependencies([x_plus_1]):
y = x
init = tf.initialize_all_variables()
with tf.Session() as session:
init.run()
for i in xrange(5):
print(y.eval())
它不会:它会打印0,0,0,0,0。相反,我们似乎需要在control\u dependencies
块中向图形添加一个新节点。所以我们使用这个技巧:
x = tf.Variable(0.0)
x_plus_1 = tf.assign_add(x, 1)
with tf.control_dependencies([x_plus_1]):
y = tf.identity(x)
init = tf.initialize_all_variables()
with tf.Session() as session:
init.run()
for i in xrange(5):
print(y.eval())
这是有效的:它打印1,2,3,4,5
如果在CIFAR-10教程中,我们放弃了
tf.identity
,那么丢失\u平均值\u op
将永远不会运行。我遇到了另一个未被其他答案完全覆盖的用例
def conv_layer(input_tensor, kernel_shape, output_dim, layer_name, decay=None, act=tf.nn.relu):
"""Reusable code for making a simple convolutional layer.
"""
# Adding a name scope ensures logical grouping of the layers in the graph.
with tf.name_scope(layer_name):
# This Variable will hold the state of the weights for the layer
with tf.name_scope('weights'):
weights = weight_variable(kernel_shape, decay)
variable_summaries(weights, layer_name + '/weights')
with tf.name_scope('biases'):
biases = bias_variable([output_dim])
variable_summaries(biases, layer_name + '/biases')
with tf.name_scope('convolution'):
preactivate = tf.nn.conv2d(input_tensor, weights, strides=[1, 1, 1, 1], padding='SAME')
biased = tf.nn.bias_add(preactivate, biases)
tf.histogram_summary(layer_name + '/pre_activations', biased)
activations = act(biased, 'activation')
tf.histogram_summary(layer_name + '/activations', activations)
return activations
大多数情况下,在构建卷积层时,您只需要返回激活,以便可以将这些激活反馈到下一层。但是,有时,例如在构建自动编码器时,您需要预激活值
在这种情况下,一个优雅的解决方案是将tf.identity作为激活函数传递,有效地不激活层。我在Tensorboard中发现了tf.identity的另一个应用。 如果使用tf.shuffle\u batch,它会一次返回多个张量,因此在可视化图形时会看到混乱的画面,无法将张量创建管道与活动输入张量分开:
但是使用tf.identity,您可以创建重复的节点,这不会影响计算流:除上述内容外,我只需在需要为没有名称参数的ops分配名称时使用它,就像在RNN中初始化状态时一样:
rnn_cell = tf.contrib.rnn.MultiRNNCell([cells])
# no name arg
initial_state = rnn_cell.zero_state(batch_size,tf.float32)
# give it a name with tf.identity()
initial_state = tf.identity(input=initial_state,name="initial_state")
在分配培训中,我们应该使用tf.identity,否则工人将挂在等待首席工人初始化的位置:
vec = tf.identity(tf.nn.embedding_lookup(embedding_tbl, id)) * mask
with tf.variable_scope("BiRNN", reuse=None):
out, _ = tf.nn.bidirectional_dynamic_rnn(fw, bw, vec, sequence_length=id_sz, dtype=tf.float32)
关于详细信息,如果没有标识,首席工作人员会不适当地将某些变量视为局部变量,而其他工作人员则等待初始化操作,当我们的输入数据以字节序列化时,初始化操作无法结束,我们希望从该数据集提取特征。我们可以在键值格式中这样做,然后为它获取一个占位符。当有多个功能并且每个功能必须以不同的格式读取时,它的好处会更加明显
#read the entire file in this placeholder
serialized_tf_example = tf.placeholder(tf.string, name='tf_example')
#Create a pattern in which data is to be extracted from input files
feature_configs = {'image': tf.FixedLenFeature(shape=[256], dtype=tf.float32),/
'text': tf.FixedLenFeature(shape=[128], dtype=tf.string),/
'label': tf.FixedLenFeature(shape=[128], dtype=tf.string),}
#parse the example in key: tensor dictionary
tf_example = tf.parse_example(serialized_tf_example, feature_configs)
#Create seperate placeholders operation and tensor for each feature
image = tf.identity(tf_example['image'], name='image')
text = tf.identity(tf_example['text'], name='text')
label = tf.identity(tf_example['text'], name='label')
我看到这种检查断言的黑客行为:
assertion = tf.assert_equal(tf.shape(image)[-1], 3, message="image must have 3 color channels")
with tf.control_dependencies([assertion]):
image = tf.identity(image)
此外,它仅用于给出一个名称:
image = tf.identity(image, name='my_image')
如果可能的话,你能对我上面的更新发表评论吗?具体来说,如果我们省略了行
total_loss=tf.identity(total_loss)
,会出什么问题呢?嘿,在我写下答案一小时后,把我的答案包括在你的答案中做得很好。如果输出是张量列表,我可以直接使用identity还是使用第一个堆栈,然后使用identity?最好的方法是什么?假设您有一个包含两个参数的图:image和label。您已经实现了两种输入值的方法:使用占位符和tf.shuffle\u batch
。您希望将图形很好地可视化。让我们拆分训练子图和批生成子图。使用占位符很容易。但批处理不是:如果将操作tf.shuffle\u batch放入作用域batch\u generation
,将其他操作放入作用域model
,则model
内没有输入节点。我建议使用tf