Нет более простого способа, чем то, что вам уже сказали. Поначалу этот способ может показаться сложным, но на самом деле он действительно прост. Вам просто нужно использовать API низкого уровня, чтобы вручную рассчитать градиенты для каждого пакета, усреднить по ним и затем вручную передать усредненные градиенты оптимизатору, чтобы применить их.
Я постараюсь предоставить несколько урезанных кодов, как это сделать. Я буду использовать точки в качестве заполнителей для реального кода, который будет зависеть от проблемы. То, что вы обычно делаете, будет примерно таким:
import tensorflow as tf
[...]
input = tf.placeholder(...)
[...]
loss = ...
[...]
# initialize the optimizer
optimizer = tf.train.AdamOptimizer(LEARNING_RATE)
# define operation to apply the gradients
minimize = optimizer.minimize(loss)
[...]
if __name__ == '__main__':
session = tf.Session(config=CONFIG)
session.run(tf.global_variables_initializer())
for step in range(1, MAX_STEPS + 1):
data = ...
loss = session.run([minimize, loss],
feed_dict={input: data})[1]
То, что вы хотите сделать вместо этого сейчас, для усреднения по нескольким пакетам в память консерванта будет выглядеть так:
import tensorflow as tf
[...]
input = tf.placeholder(...)
[...]
loss = ...
[...]
# initialize the optimizer
optimizer = tf.train.AdamOptimizer(LEARNING_RATE)
# grab all trainable variables
trainable_variables = tf.trainable_variables()
# define variables to save the gradients in each batch
accumulated_gradients = [tf.Variable(tf.zeros_like(tv.initialized_value()),
trainable=False) for tv in
trainable_variables]
# define operation to reset the accumulated gradients to zero
reset_gradients = [gradient.assign(tf.zeros_like(gradient)) for gradient in
accumulated_gradients]
# compute the gradients
gradients = optimizer.compute_gradients(loss, trainable_variables)
# Note: Gradients is a list of tuples containing the gradient and the
# corresponding variable so gradient[0] is the actual gradient. Also divide
# the gradients by BATCHES_PER_STEP so the learning rate still refers to
# steps not batches.
# define operation to evaluate a batch and accumulate the gradients
evaluate_batch = [
accumulated_gradient.assign_add(gradient[0]/BATCHES_PER_STEP)
for accumulated_gradient, gradient in zip(accumulated_gradients,
gradients)]
# define operation to apply the gradients
apply_gradients = optimizer.apply_gradients([
(accumulated_gradient, gradient[1]) for accumulated_gradient, gradient
in zip(accumulated_gradients, gradients)])
# define variable and operations to track the average batch loss
average_loss = tf.Variable(0., trainable=False)
update_loss = average_loss.assign_add(loss/BATCHES_PER_STEP)
reset_loss = average_loss.assign(0.)
[...]
if __name__ == '__main__':
session = tf.Session(config=CONFIG)
session.run(tf.global_variables_initializer())
data = [batch_data[i] for i in range(BATCHES_PER_STEP)]
for batch_data in data:
session.run([evaluate_batch, update_loss],
feed_dict={input: batch_data})
# apply accumulated gradients
session.run(apply_gradients)
# get loss
loss = session.run(average_loss)
# reset variables for next step
session.run([reset_gradients, reset_loss])
Это должно быть работоспособно, если вы заполните пробелы. Однако, возможно, я допустил ошибку, урезав ее и вставив сюда. Для работающего примера вы можете взглянуть на проект Я сейчас работаю над собой.
Я также хочу пояснить, что это не то же самое, что оценка потерь для всех пакетных данных одновременно, поскольку вы усредняете по градиентам. Это особенно важно, когда ваша потеря плохо работает с низкой статистикой. Возьмем, например, квадрат хи гистограмм, вычисление средних градиентов для квадрата хи гистограмм с низким количеством бинов не будет столь же хорошим, как вычисление градиента только для одной гистограммы, когда все бины заполнены одновременно.