[Deep Q-Network]Tensorflow自动微分时如何排除ops
[Deep Q-Network]How to exclude ops at auto-differential of Tensorflow
我正在尝试使用 Tensorflow 创建类似于 Deepmind DQN3.0 的深度 Q 网络 (DQN),但我遇到了一些困难。我认为原因是 TensorFlow 的自动微分方法。
请看这张照片。这是DQN3.0的架构
在监督学习中,为了让网络的输出逼近到标签,通过损失函数计算差值,反向传播,用优化器更新参数。
在DQN中,AI过去经历过的状态积累在记忆中,再次输入到TergetNetwork和Network这两个神经网络,两个网络的差异体现在Network中。
每个网络的输出不是总数为1的概率而是期望值。
TergetNetwork 的输出将包括折扣率(gamma) 和当时获得的奖励。
并且,看DQN 3.0(lua + torch)的实现,它将当前网络的输出与当时选择的action进行比较,通过backward方法直接向后传播差异.
function nql:getQUpdate(args)
local s, a, r, s2, term, delta
local q, q2, q2_max
s = args.s
a = args.a
r = args.r
s2 = args.s2
term = args.term
-- The order of calls to forward is a bit odd in order
-- to avoid unnecessary calls (we only need 2).
-- delta = r + (1-terminal) * gamma * max_a Q(s2, a) - Q(s, a)
term = term:clone():float():mul(-1):add(1)
local target_q_net
if self.target_q then
target_q_net = self.target_network
else
target_q_net = self.network
end
-- Compute max_a Q(s_2, a).
q2_max = target_q_net:forward(s2):float():max(2)
-- Compute q2 = (1-terminal) * gamma * max_a Q(s2, a)
q2 = q2_max:clone():mul(self.discount):cmul(term)
delta = r:clone():float()
if self.rescale_r then
delta:div(self.r_max)
end
delta:add(q2)
-- q = Q(s,a)
local q_all = self.network:forward(s):float()
q = torch.FloatTensor(q_all:size(1))
for i=1,q_all:size(1) do
q[i] = q_all[i][a[i]]
end
delta:add(-1, q)
if self.clip_delta then
delta[delta:ge(self.clip_delta)] = self.clip_delta
delta[delta:le(-self.clip_delta)] = -self.clip_delta
end
local targets = torch.zeros(self.minibatch_size, self.n_actions):float()
for i=1,math.min(self.minibatch_size,a:size(1)) do
targets[i][a[i]] = delta[i]
end
if self.gpu >= 0 then targets = targets:cuda() end
return targets, delta, q2_max
end
function nql:qLearnMinibatch()
-- Perform a minibatch Q-learning update:
-- w += alpha * (r + gamma max Q(s2,a2) - Q(s,a)) * dQ(s,a)/dw
assert(self.transitions:size() > self.minibatch_size)
local s, a, r, s2, term = self.transitions:sample(self.minibatch_size)
local targets, delta, q2_max = self:getQUpdate{s=s, a=a, r=r, s2=s2,
term=term, update_qmax=true}
-- zero gradients of parameters
self.dw:zero()
-- get new gradient
self.network:backward(s, targets)
因此,如果你不介意上图中的计算块的速度,你可以在CPU上使用Numpy等计算,而不是使用Tensorflow,我可以排除我在想它来自自动微分。
在 DQN3.0 中,仅从 Network(蓝色)的输出层计算反向传播。但是,对于我在 Tensorflow 中的模型,它从最终操作 mul
.
开始
我想使用 Tensorflow 从与 DQN3.0 中相同的输出层开始反向传播。
我知道我可以使用 compute_gradients() 优化器方法和 运行 从头开始创建的手动微分过程来获得 grads_and_vars
。但是,我认为实现这样一个卷积层的差异对我来说是非常困难的。
我可以使用 Tensorflow 函数或其他方法在自动微分时排除计算块操作吗?还是有其他方法可以解决?
你问的问题与训练你的网络不兼容。
反向传播起点是您的损失函数(a.k.a 红色块)。在这个损失函数中,所有可以微分的操作都会,这样梯度就可以"flow"通过网络。您在此过程中 "exclude" 的每个操作(例如使用 tf.stop_gradient)都将成为反向传播的停止点,并且梯度不会流向您的操作所依赖的每个值。
基本上是什么意思?如果排除 "compute block",则无法计算任何变量的梯度。
谢谢大家
我暂时解决了排除问题
我创建了修改 tf.gradients 函数的原始函数,如下所示。
def gradients(ys,
xs,
grad_start, #***** ←Add arguments that new gradient start op ******
grad_ys=None,
name="gradients",
colocate_gradients_with_ops=False,
gate_gradients=False,
aggregation_method=None):
.
.
.
# The set of 'from_ops'.
stop_ops = _StopOps(from_ops, pending_count)
while queue:
# generate gradient subgraph for op.
op = queue.popleft()
with _maybe_colocate_with(op, colocate_gradients_with_ops):
if loop_state:
loop_state.EnterGradWhileContext(op, before=True)
out_grads = _AggregatedGrads(grads, op, loop_state, aggregation_method)
if loop_state:
loop_state.ExitGradWhileContext(op, before=True)
#*************************************************************
# Add 2 line that replace 'out_grads' op to new grad start op
if grad_start is not None and op == grad_start.op:
out_grads = ys
.
.
.
正如我用 Tensorboard 确认的那样,它看起来符合预期。
https://i.stack.imgur.com/vG1e0.png
我正在尝试使用 Tensorflow 创建类似于 Deepmind DQN3.0 的深度 Q 网络 (DQN),但我遇到了一些困难。我认为原因是 TensorFlow 的自动微分方法。
请看这张照片。这是DQN3.0的架构
在监督学习中,为了让网络的输出逼近到标签,通过损失函数计算差值,反向传播,用优化器更新参数。
在DQN中,AI过去经历过的状态积累在记忆中,再次输入到TergetNetwork和Network这两个神经网络,两个网络的差异体现在Network中。
每个网络的输出不是总数为1的概率而是期望值。 TergetNetwork 的输出将包括折扣率(gamma) 和当时获得的奖励。
并且,看DQN 3.0(lua + torch)的实现,它将当前网络的输出与当时选择的action进行比较,通过backward方法直接向后传播差异.
function nql:getQUpdate(args)
local s, a, r, s2, term, delta
local q, q2, q2_max
s = args.s
a = args.a
r = args.r
s2 = args.s2
term = args.term
-- The order of calls to forward is a bit odd in order
-- to avoid unnecessary calls (we only need 2).
-- delta = r + (1-terminal) * gamma * max_a Q(s2, a) - Q(s, a)
term = term:clone():float():mul(-1):add(1)
local target_q_net
if self.target_q then
target_q_net = self.target_network
else
target_q_net = self.network
end
-- Compute max_a Q(s_2, a).
q2_max = target_q_net:forward(s2):float():max(2)
-- Compute q2 = (1-terminal) * gamma * max_a Q(s2, a)
q2 = q2_max:clone():mul(self.discount):cmul(term)
delta = r:clone():float()
if self.rescale_r then
delta:div(self.r_max)
end
delta:add(q2)
-- q = Q(s,a)
local q_all = self.network:forward(s):float()
q = torch.FloatTensor(q_all:size(1))
for i=1,q_all:size(1) do
q[i] = q_all[i][a[i]]
end
delta:add(-1, q)
if self.clip_delta then
delta[delta:ge(self.clip_delta)] = self.clip_delta
delta[delta:le(-self.clip_delta)] = -self.clip_delta
end
local targets = torch.zeros(self.minibatch_size, self.n_actions):float()
for i=1,math.min(self.minibatch_size,a:size(1)) do
targets[i][a[i]] = delta[i]
end
if self.gpu >= 0 then targets = targets:cuda() end
return targets, delta, q2_max
end
function nql:qLearnMinibatch()
-- Perform a minibatch Q-learning update:
-- w += alpha * (r + gamma max Q(s2,a2) - Q(s,a)) * dQ(s,a)/dw
assert(self.transitions:size() > self.minibatch_size)
local s, a, r, s2, term = self.transitions:sample(self.minibatch_size)
local targets, delta, q2_max = self:getQUpdate{s=s, a=a, r=r, s2=s2,
term=term, update_qmax=true}
-- zero gradients of parameters
self.dw:zero()
-- get new gradient
self.network:backward(s, targets)
因此,如果你不介意上图中的计算块的速度,你可以在CPU上使用Numpy等计算,而不是使用Tensorflow,我可以排除我在想它来自自动微分。
在 DQN3.0 中,仅从 Network(蓝色)的输出层计算反向传播。但是,对于我在 Tensorflow 中的模型,它从最终操作 mul
.
我想使用 Tensorflow 从与 DQN3.0 中相同的输出层开始反向传播。
我知道我可以使用 compute_gradients() 优化器方法和 运行 从头开始创建的手动微分过程来获得 grads_and_vars
。但是,我认为实现这样一个卷积层的差异对我来说是非常困难的。
我可以使用 Tensorflow 函数或其他方法在自动微分时排除计算块操作吗?还是有其他方法可以解决?
你问的问题与训练你的网络不兼容。
反向传播起点是您的损失函数(a.k.a 红色块)。在这个损失函数中,所有可以微分的操作都会,这样梯度就可以"flow"通过网络。您在此过程中 "exclude" 的每个操作(例如使用 tf.stop_gradient)都将成为反向传播的停止点,并且梯度不会流向您的操作所依赖的每个值。
基本上是什么意思?如果排除 "compute block",则无法计算任何变量的梯度。
谢谢大家
我暂时解决了排除问题
我创建了修改 tf.gradients 函数的原始函数,如下所示。
def gradients(ys,
xs,
grad_start, #***** ←Add arguments that new gradient start op ******
grad_ys=None,
name="gradients",
colocate_gradients_with_ops=False,
gate_gradients=False,
aggregation_method=None):
.
.
.
# The set of 'from_ops'.
stop_ops = _StopOps(from_ops, pending_count)
while queue:
# generate gradient subgraph for op.
op = queue.popleft()
with _maybe_colocate_with(op, colocate_gradients_with_ops):
if loop_state:
loop_state.EnterGradWhileContext(op, before=True)
out_grads = _AggregatedGrads(grads, op, loop_state, aggregation_method)
if loop_state:
loop_state.ExitGradWhileContext(op, before=True)
#*************************************************************
# Add 2 line that replace 'out_grads' op to new grad start op
if grad_start is not None and op == grad_start.op:
out_grads = ys
.
.
.
正如我用 Tensorboard 确认的那样,它看起来符合预期。 https://i.stack.imgur.com/vG1e0.png