我的主要问题是;对损失进行平均与对梯度进行平均一样,如何在小批量中累积损失,然后计算梯度?</ p>
我一直在尝试在Tensorflow中实现策略梯度,并遇到无法将所有游戏状态立即馈入我的网络然后进行更新的问题。问题是,如果我降低网络规模,然后立即在所有帧上进行训练,并求出损失的均值,那么它将开始很好地收敛。但是,如果我在小批量上累积梯度然后求平均值,则梯度会爆炸并且重量会溢出。
任何帮助或见识将不胜感激。
请记住,这是我第一次在这里提问。
答案 0 :(得分:0)
您可以做的是在每个微型批处理之后累积梯度,然后根据梯度平均值更新权重。考虑以下简单情况,用单层感知器拟合50个高斯斑点:
from sklearn.datasets import make_blobs
import tensorflow as tf
import numpy as np
x_train, y_train = make_blobs(n_samples=50,
n_features=2,
centers=[[1, 1], [-1, -1]],
cluster_std=0.5)
with tf.name_scope('x'):
x = tf.placeholder(tf.float32, [None, 2])
y = tf.placeholder(tf.int32, [None])
with tf.name_scope('layer'):
logits = tf.layers.dense(x,
units=2,
kernel_initializer=tf.contrib.layers.xavier_initializer())
with tf.name_scope('loss'):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
loss_op = tf.reduce_mean(xentropy)
张量流优化器的minimize()
方法调用compute_gradients()
,然后调用apply_gradients()
。我将不直接调用minimize()
,而是直接调用这两个方法。首先,要获取渐变,我们调用compute_gradients()
(返回元组列表grads_and_vars
),对于apply_gradients()
而不是渐变,我将使用占位符作为未来渐变的平均值:>
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
grads_and_vars = optimizer.compute_gradients(loss_op)
grads = [g for g, v in grads_and_vars]
# placeholders for gradients averages
placeholder_grads = [tf.placeholder(tf.float32, [None] + g.get_shape().as_list())
for g in grads]
new_grads_and_vars = [(tf.reduce_mean(p, axis=0), gv[1])
for p, gv in zip(placeholder_grads, grads_and_vars)]
apply_grads_op = optimizer.apply_gradients(new_grads_and_vars)
在小批量生产中,我们仅计算损失(您也可以累积损失-附加到一些列表中,然后计算平均值)和梯度,而无需对权重应用梯度。在每个纪元结束时,我们执行apply_grads_op
操作,同时向其占位符提供累积的渐变:
data = tf.data.Dataset.from_tensor_slices({'x':x_train, 'y':y_train}).batch(10)
iterator = data.make_initializable_iterator()
n_epochs = 2
with tf.Session() as sess:
_ = sess.run([tf.global_variables_initializer(), iterator.initializer])
next_batch = iterator.get_next()
for epoch in range(n_epochs):
epoch_grads = []
while True:
try:
batch = sess.run(next_batch)
evaled = sess.run([loss_op] + grads,
feed_dict={x:batch['x'], y:batch['y']})
epoch_grads.append(evaled[1:])
print('batch loss:', evaled[0])
except tf.errors.OutOfRangeError:
_ = sess.run(iterator.initializer)
feed_dict = {p:[g[i] for g in epoch_grads]
for i, p in enumerate(placeholder_grads)}
_ = sess.run(apply_grads_op, feed_dict=feed_dict)
break