我有一个网络,它使用Nx3
矩阵作为输入并产生N维向量。假设批量大小为1且N = 1024,所以输出的形状为(1,1024)
。我想针对输入针对输出的每个维度计算渐变。也就是说,每dy/dx
就有y
。但是,张量流的tf.gradients
计算d sum(y)/dx
的总和。我知道没有一种简单的方法可以计算每个输出维的梯度,因此我最终决定运行tf.gradients
1024次,因为我只需要在项目中执行一次,就不必再执行一次。
所以我这样做:
start = datetime.datetime.now()
output_code_split = tf.split(output_code,1024)
#output shape = (1024,)
grad_ops = []
for i in range(1024):
gr = tf.gradients(output_code_split[i],input)
#output shape = (1024,1,16,1024,3) , where 16= batch size
gr = tf.reduce_mean(gr,[0,1,2,3])
#output shape = (1024,)
grad_ops.append(gr)
present = datetime.datetime.now()
print(i,(present-start).seconds,flush=True)
#prints time taken to finish previous computation.
start = datetime.datetime.now()
当代码开始运行时,两次迭代之间的时间 为4秒,因此我认为它将运行大约4096秒。但是,随着迭代次数的增加,后续运行所花费的时间也不断增加。间隔是在代码启动时为4秒,在大约500次迭代后最终达到30秒,这太大了。
保存渐变操作grad_ops
的列表是否更大并且占用更多内存。不幸的是,我无法对此代码进行详细的内存分析。有关导致迭代时间随时间推移而耗费时间的任何想法?
(请注意,在代码中,我仅创建渐变操作而不是实际评估它们。稍后介绍该部分,但由于上述极端缓慢的原因,我的代码未到达该位置)
谢谢。
答案 0 :(得分:0)
浪费执行时间的是,您在for循环的每次迭代中都在图上定义了一个新操作。对tf.gradient
和tf.reduce_mean
的每次调用都会在图上推送一个新节点。然后需要重新编译才能运行。实际应该为您使用的是将tf.gather
与一个int32占位符一起使用,该占位符为渐变操作提供尺寸。像这样:
idx_placeholder = tf.placeholder(tf.int32, shape=(None,))
grad_operation = tf.gradients(tf.gather(output_code_split, idx_placeholder))
for i in range(1024):
sess.run(grad_operation, {idx_placeholder: np.array([i])})