与 Eager 和 Graph 模式无关的 Tensorflow 训练
Posted
技术标签:
【中文标题】与 Eager 和 Graph 模式无关的 Tensorflow 训练【英文标题】:A Tensorflow training agnostic to Eager and Graph modes 【发布时间】:2018-07-30 03:12:07 【问题描述】:我花了一些时间在 Tensorflow 中编写新颖的(我希望的)RNN 单元。 为了原型,我使用渴望模式(更容易调试)。 为了训练,我将代码迁移到图表(运行速度更快)。
我正在寻找一个包装器代码/示例,它可以以一种与我运行它的模式无关的方式运行前向传递和训练 - 尽可能多地渴望或图形。我想到了一组函数/类,可以在其中插入特定的神经网络/优化器/数据,并且这些函数/类集可以在两种模式下运行,而两者之间的变化最小。另外,能兼容多种类型的神经网络/优化器/数据实例当然是好事。
我很确定很多人都有这个想法。 考虑到 TF 中当前的 Eager/Graph 集成,我想知道这样的事情是否可行。
【问题讨论】:
【参考方案1】:是的。我一直在想同样的事情。在Tensorflow documentation可以看到:
为 Eager Execution 编写的相同代码还将在图形执行期间构建图形。只需在未启用 Eager Execution 的新 Python 会话中运行相同的代码即可。
但这很难实现,主要是因为处理图形意味着处理占位符,而占位符不能在 Eager 模式下使用。我尝试使用面向对象的层和 Dataset API 摆脱占位符。这是我能得到的最接近完全兼容的代码:
m = 128 # num_examples
n = 5 # num features
epochs = 2
batch_size = 32
steps_per_epoch = m // 32
dataset = tf.data.Dataset.from_tensor_slices(
(tf.random_uniform([m, n], dtype=tf.float32),
tf.random_uniform([m, 1], dtype=tf.float32)))
dataset = dataset.repeat(epochs)
dataset = dataset.batch(batch_size)
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu', input_dim=n),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(1)
])
def train_eagerly(model, dataset):
optimizer = tf.train.AdamOptimizer()
iterator = dataset.make_one_shot_iterator()
print('Training graph...')
for epoch in range(epochs):
print('Epoch', epoch)
progbar = tf.keras.utils.Progbar(target=steps_per_epoch, stateful_metrics='loss')
for step in range(steps_per_epoch):
with tf.GradientTape() as tape:
features, labels = iterator.get_next()
predictions = model(features, training=True)
loss_value = tf.losses.mean_squared_error(labels, predictions)
grads = tape.gradient(loss_value, model.variables)
optimizer.apply_gradients(zip(grads, model.variables))
progbar.add(1, values=[('loss', loss_value.numpy())])
def train_graph(model, dataset):
optimizer = tf.train.AdamOptimizer()
iterator = dataset.make_initializable_iterator()
print('Training graph...')
with tf.Session() as sess:
sess.run(iterator.initializer)
sess.run(tf.global_variables_initializer())
for epoch in range(epochs):
print('Epoch', epoch)
progbar = tf.keras.utils.Progbar(target=steps_per_epoch, stateful_metrics='loss')
for step in range(steps_per_epoch):
with tf.GradientTape() as tape:
features, labels = sess.run(iterator.get_next())
predictions = model(features, training=True)
loss_value = tf.losses.mean_squared_error(labels, predictions)
grads = tape.gradient(loss_value, model.variables)
optimizer.apply_gradients(zip(grads, model.variables))
progbar.add(1, values=[('loss', loss_value.eval())])
如您所见,主要区别在于我在 Eager 训练期间使用 one_shot_iterator(当然,在图训练期间,我必须在会话中运行操作)。
我尝试使用 optimizer.minimize
来做同样的事情,而不是自己应用渐变,但我想不出一个既适用于 Eager 模式又适用于图形模式的代码。
此外,我敢肯定,对于不那么简单的模型(例如您正在使用的模型),这将变得更加困难。
【讨论】:
以上是关于与 Eager 和 Graph 模式无关的 Tensorflow 训练的主要内容,如果未能解决你的问题,请参考以下文章
tensorflow版本2.0和1.0兼容问题:The Session graph is empty. Add operations to the graph before calling run()
将 tf.Tensor 转换为 numpy 数组,然后将其保存为图像而不使用 eager_execution
对齐PyTorch,一文详解OneFlow的DataLoader实现