我使用tensorflow重新实现了论文Learning Image Matching by Simply Watching Video,并且在从网络抓取渐变时遇到了一些严重的性能问题。为了快速回顾他们在论文中所做的事情,他们拥有训练有素的网络,他们做了1个前向道具来获得插值图像,然后他们做了w * h / stride ^ 2 backprops来获得每个输入的输出的梯度。像素。由于反向传播的数量很多,这必须相当有效地完成,以便在合理的时间内获得梯度(在论文中,每个反向提升的时间为8分钟,150毫秒时间为128 * 384/16像素(步幅4)在行和列上))。由于在张量流中,由于梯度聚合而无法对多个反向支持进行批处理(例如参见this discussion),我需要执行以下操作:
for i in range(0, h, stride):
for j in range(0, w, stride):
grad_output[0,i,j,:] = 1 #select current pixel
grad.append(tf.gradients(predictions, images, grad_output))
grad_output[grad_output != 0] = 0
获取每个像素的符号渐变,其中预测是网络的输出张量,图像是输入,声明为in gpu常量:
with tf.device('/gpu:0'):
images = tf.constant(inp, dtype=tf.float32)
其中inp是包含数据的实际numpy数组。
每次对tf.gradients
的调用大约需要0.35毫秒,这与作者在论文中的报告相比已经过多了。但是在评估符号渐变时花费的时间最多,如:
for i in range(0, len(grad)):
res = sess.run(grad[i])
这需要大约1.5秒,非常慢。现在,对sess.run(grad[i])
(具有相同索引i
)的后续调用非常快,大约100毫秒,而在每次迭代运行for循环更改i
导致每次迭代大约1.5秒。在看到这种行为后,我的猜测是将内容移到GPU上会有很大的开销,是否可能?如果是这种情况,我该如何避免呢?我已经将images
张量移到GPU常量而不是使用占位符并依赖feed_dict
中的sess.run
,但这对性能没有任何明显的影响。任何加速评估符号渐变的想法?我觉得我在这里错过了一些简单的东西,因为1个反向启动需要1.5秒才真正远离任何现实场景(训练网络能够每秒处理大约100个样本,所以它不是架构问题我猜..)
谢谢!
答案 0 :(得分:0)
以下是我的想法:
tf.gradients
看起来很可疑 - 请确保您没有创建超过必要的张量。如果它不改变您的语义,请尝试一次计算所有渐变:
res = sess.run(grad)
假设grad
是张量列表。在循环中执行sess.run
会多次重新计算grad[i]
和grad[j]
的常见副本。
希望它有所帮助!