Tensorflow 如何将渐变列表或(渐变、变量名)对提供给我的模型

Tensorflow 如何将渐变列表或(渐变、变量名)对提供给我的模型,tensorflow,Tensorflow,这与前面的一个问题有关:,也与;但是,我仍然找不到确切的答案。例如,另一个相关问题的答案不适合我(顺便说一句,它没有被接受,也没有更多的评论) 我想尝试模拟更大的批量,但只使用一个GPU。 因此,我需要计算每个小批量的梯度,在几个这样的小批量中聚合/平均它们,然后应用 (基本上,它类似于同步分布式SGD,但在单个设备/GPU上连续执行。当然,分布式SGD的加速优势已经丧失,但更大的批量本身可能会使收敛到更高的精度和更大的步长,正如最近几篇论文所指出的。) 为了保持低内存需求,我应该使用小批量执行

这与前面的一个问题有关:,也与;但是,我仍然找不到确切的答案。例如,另一个相关问题的答案不适合我(顺便说一句,它没有被接受,也没有更多的评论)

我想尝试模拟更大的批量,但只使用一个GPU。 因此,我需要计算每个小批量的梯度,在几个这样的小批量中聚合/平均它们,然后应用

(基本上,它类似于同步分布式SGD,但在单个设备/GPU上连续执行。当然,分布式SGD的加速优势已经丧失,但更大的批量本身可能会使收敛到更高的精度和更大的步长,正如最近几篇论文所指出的。)

为了保持低内存需求,我应该使用小批量执行标准SGD,在每次迭代后更新梯度,然后调用
optimizer.apply_gradients()
(其中
optimizer
是实现的优化器之一)

所以,一切看起来都很简单,但当我去实现它时,它实际上并不是那么简单

例如,我想使用一个
,为每个迭代计算梯度,然后,当处理多个批次时,求和梯度并将它们传递给我的模型。但是列表本身不能输入到
sess.run
feed\u dict
参数中。另外,直接传递渐变并不完全有效,我得到了
TypeError:unhabable类型:“numpy.ndarray”
(我想原因是我不能传递
numpy.ndarray
,只有tensorflow变量)。 我可以为渐变定义一个占位符,但为此我需要首先构建模型(以指定可训练变量等)


总而言之,请告诉我有一个更简单的方法来实现这一点。

没有比已经告诉你的更简单的方法了。这种方式一开始可能看起来很复杂,但实际上很简单。您只需使用低级API手动计算每个批次的梯度,对其进行平均,然后手动将平均梯度提供给优化器以应用它们

我将尝试提供一些关于如何执行此操作的精简代码。我将使用点作为实际代码的占位符,这取决于问题。您通常会这样做:

将tensorflow导入为tf
[...]
输入=tf.占位符(…)
[...]
损失=。。。
[...]
#初始化优化器
优化器=tf.train.AdamOptimizer(学习率)
#定义应用渐变的操作
最小化=优化器。最小化(损失)
[...]
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
session=tf.session(config=config)
session.run(tf.global\u variables\u initializer())
对于步进范围(1,最大步数+1):
数据=。。。
丢失=会话。运行([最小化,丢失],
feed_dict={input:data})[1]
您现在要做的是,对多个批次进行平均以保留内存:

将tensorflow导入为tf
[...]
输入=tf.占位符(…)
[...]
损失=。。。
[...]
#初始化优化器
优化器=tf.train.AdamOptimizer(学习率)
#获取所有可训练变量
可训练的_变量=tf.可训练的_变量()
#定义变量以保存每个批次中的渐变
累积梯度=[tf.Variable(tf.zeros_like(tv.initialized_value()),
可培训=错误)用于电视输入
可训练变量]
#定义将累积梯度重置为零的操作
重置梯度=[gradient.assign(tf.zeros_like(gradient)),用于中的梯度
累积梯度]
#计算梯度
梯度=优化器。计算梯度(损失、可训练的变量)
#注意:渐变是一个元组列表,包含渐变和
#对应的变量so gradient[0]是实际的梯度。也分
#每一步按批次进行梯度,因此学习率仍然是指
#步骤不是批次。
#定义用于评估批次和累积梯度的操作
评估批次=[
累计梯度。分配添加(梯度[0]/每步批次)
对于累积的_梯度,zip中的梯度(累积的_梯度,
梯度)]
#定义应用渐变的操作
apply_gradients=优化器。apply_gradients([
(累积梯度,梯度[1])对于累积梯度,梯度
在zip中(累积的坡度,坡度)])
#定义变量和操作以跟踪平均批次损失
平均损耗=tf.变量(0,可训练=假)
更新损失=平均损失。分配添加(每步损失/批次)
重置损失=平均损失。分配(0)
[...]
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
session=tf.session(config=config)
session.run(tf.global\u variables\u initializer())
数据=[范围内i的批处理数据[i](每步批处理)]
对于数据中的批处理数据:
会话运行([评估批处理,更新丢失],
feed_dict={input:batch_data})
#应用累积梯度
会话.运行(应用梯度)
#迷路
损耗=会话运行(平均损耗)
#为下一步重置变量
会话运行([重置梯度,重置丢失])
如果你填补了空白,这应该是可以运行的。然而,我可能会犯一个错误,而剥离下来,粘贴在这里。对于一个可运行的示例,您可以查看一个我目前正在处理的问题

我还想澄清的是,这与一次评估所有批处理数据的损失不同,因为您要对梯度进行平均。当你的损失在低统计数据下不起作用时,这一点尤为重要。以卡方直方图为例,计算具有低仓位计数的卡方直方图的平均梯度不如仅计算具有所有仓位计数的一个直方图的梯度