【问题标题】:How to accumulate and appy gradients for Async n-step DQNetwork update in Tensorflow?如何在 Tensorflow 中为异步 n 步 DQNetwork 更新累积和应用梯度?
【发布时间】:2016-10-09 05:19:35
【问题描述】:

我正在尝试实现Asynchronous Methods for Deep Reinforcement Learning,其中一个步骤需要在不同步骤上累积梯度,然后应用它。 在张量流中实现这一目标的最佳方法是什么? 我已经积累了梯度,但我认为这不是实现它的最快方法(从 tensorflow 到 python 和返回的大量传输)。 欢迎任何建议。 这是我的玩具 NN 代码。它不会建模或计算任何东西,它只是执行我想要使用的操作。

import tensorflow as tf

from model import *


graph = tf.Graph()

with graph.as_default():

    state = tf.placeholder(tf.float32, shape=[None, 80,80,1])

    with tf.variable_scope('layer1'):
        W = weight_variable([8, 8, 1, 32])
        variable_summaries(W, "layer1/W")
        b = bias_variable([32])
        variable_summaries(b, "layer1/b")
        h = conv2d(state, W, 4) + b
        activation = tf.nn.relu(h)
        pool1 = max_pool_2x2(activation)

    print(pool1.get_shape())
    pool1 = tf.reshape(pool1, [-1, 3200])

    with tf.variable_scope('readout'):
        W = weight_variable([3200, 3])
        b = bias_variable([3])
        logits = tf.matmul(pool1, W) + b
        variable_summaries(h, "y")

    action_indexes = tf.placeholder(tf.int32, shape=[None], name="action_indexes")

    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, action_indexes)

    starter_learning_rate = 1e-6

    global_step = tf.Variable(0, trainable=False)

    # decay every 1000 steps with a base of 0.96:
    learning_rate = tf.train.exponential_decay(starter_learning_rate,
        global_step,
        10000, 0.96, staircase=True)

    optimizer = tf.train.RMSPropOptimizer(learning_rate)

    gradients_and_variables = optimizer.compute_gradients(loss, tf.trainable_variables())

    discounted_values = tf.placeholder(tf.float32, shape=[None, 1])

with tf.Session(graph=graph) as s:

    for v in tf.trainable_variables():
        print(v.name, v.dtype, v.get_shape())

    s.run(tf.initialize_all_variables())

    feed_dict= {
        state : np.zeros([1, 80, 80, 1]),
        action_indexes: [1],
    }


    var_to_grad = dict((var.name, grad) for grad, var in gradients_and_variables)
    keys = sorted(var_to_grad.keys())
    print(keys)

    name_to_var = dict((var.name, var) for _, var in gradients_and_variables)

    for i in range(10):

        gradients = s.run([ var_to_grad[k] for k in keys], feed_dict=feed_dict)

        for k,v in zip(keys, gradients):
            var_to_grad[k] += v

    for k in keys:
        print(var_to_grad[k])

    s.run( optimizer.apply_gradients( (g, name_to_var[v]) for v,g in var_to_grad.iteritems()), feed_dict=feed_dict)

@yaroslave 建议后更新代码:

import tensorflow as tf

from model import *


graph = tf.Graph()

with graph.as_default():

    minibatch = 32
    state = tf.placeholder(tf.float32, shape=[minibatch, 80,80,1], name="input")

    with tf.variable_scope('layer1'):
        W = weight_variable([8, 8, 1, 32])
        variable_summaries(W, "layer1/W")
        b = bias_variable([32])
        variable_summaries(b, "layer1/b")
        h = conv2d(state, W, 4) + b
        activation = tf.nn.relu(h)
        pool1 = max_pool_2x2(activation)

    print(pool1.get_shape())
    pool1 = tf.reshape(pool1, [-1, 3200])

    with tf.variable_scope('readout'):
        W = weight_variable([3200, 3])
        b = bias_variable([3])
        logits = tf.matmul(pool1, W) + b
        variable_summaries(h, "y")

    action_indexes = tf.placeholder(tf.int32, shape=[minibatch], name="action_indexes")

    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits, action_indexes)

    starter_learning_rate = 1e-6

    global_step = tf.Variable(0, trainable=False)

    # decay every 1000 steps with a base of 0.96:
    learning_rate = tf.train.exponential_decay(starter_learning_rate,
        global_step,
        10000, 0.96, staircase=True)

    optimizer = tf.train.RMSPropOptimizer(learning_rate)

    trainable_variables = tf.trainable_variables()
    varname_to_var = dict( (v.name, v) for v in trainable_variables )
    keys = sorted(varname_to_var.keys())

    gradients_and_variables = optimizer.compute_gradients(loss, [ varname_to_var[k] for k in keys])

    var_to_grad = dict((var.name, grad) for grad, var in gradients_and_variables)

    name_to_var = dict((var.name, var) for _, var in gradients_and_variables)

    # save the gradients in memory
    var_to_ref_grad = {}
    for k in keys:
        grad = var_to_grad[k]
        print(k, grad.get_shape())
        ref = tf.Variable(tf.zeros_like(grad))
        ref = ref.assign_add(grad)
        var_to_ref_grad[k] = ref

    discounted_values = tf.placeholder(tf.float32, shape=[None, 1], name='discounted_values')

    # control when to apply gradients
    compute_gradients_flag = tf.placeholder(tf.int32, name="compute_gradients")
    def fn1():
        var_grad_list = []
        for k in keys:
            grad = var_to_ref_grad[k]
            var  = varname_to_var[k]
            var_grad_list.append((grad,var))

        optimizer.apply_gradients(var_grad_list)
        return tf.no_op()

    fn2 = lambda : tf.no_op()

    last_op = tf.cond(tf.equal(compute_gradients_flag, 1), fn1, fn2)

with tf.Session(graph=graph) as s:

    feed_dict= {
        state : np.zeros([minibatch, 80, 80, 1]),
        action_indexes: [1],
        compute_gradients_flag: False,
    }

    s.run(tf.initialize_all_variables())

    for i in range(10):

        # accumulate gradients
        s.run(last_op, feed_dict=feed_dict)

【问题讨论】:

  • 您可以通过运行assign 将梯度保存在变量中而不是获取值的操作将所有内容保留在 TF 中,然后执行 assign_add 而不是累积
  • @YaroslavBulatov 你认为 TF 会为这样的实现添加更多接口吗?如果我们也可以将 TF 用于强化学习,那就太好了。
  • @SungKim 有一个即时执行接口in the works,因此您可以使用标准 Python 构造,同时将数据保存在 GPU 上
  • @YaroslavBulatov 所以我按照你的建议更新了代码,但现在有趣的是tf.initialize_all_variables() 需要运行图中的操作来初始化变量。也许我做错了,我不必使用 initialize_all_variables 并手动初始化它们。
  • 嗯,我不明白这个问题,initialize_all_variables 应该只运行初始化程序来设置变量的初始值,它不应该运行什么?

标签: neural-network tensorflow reinforcement-learning


【解决方案1】:

您实际上不必手动累积渐变。您可以通过批量应用推出更新来让 Tensorflow 为您累积它们。

s_list = list_of_states_visited
a_list = list_of_actions_taken
R_list = list_of_value_targets

sess.run(local_net.update, feed_dict={
    local_net.input: s_list,
    local_net.a: a_list,
    local_net.R: R_list
})

【讨论】:

    【解决方案2】:

    这样的东西可能会创建用于累积梯度、重置累积梯度和应用累积梯度的操作(未经测试!):

    def build_gradient_accumulators(optimizer, gradients_and_variables):
        accum_grads_and_vars = []
        accumulators = []
        resetters = []
    
        for grad, var in gradients_and_variables:
            accum = tf.Variable(tf.zeros_like(grad))
            accum = accum.assign_add(grad)
            accumulators.append(accum)
            accum_grads_and_vars.append((accum, var))
            resetters.append(tf.assign(accum, tf.zeros_like(accum)))
    
        reset_op = tf.group(*resetters)
        accum_op = tf.group(*accumulators)
        apply_op = optimizer.apply_gradients(accum_grads_and_vars)
        return reset_op, accum_op, apply_op
    

    【讨论】:

      猜你喜欢
      • 2021-06-08
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 2018-03-28
      相关资源
      最近更新 更多