【问题标题】:A Tensorflow training agnostic to Eager and Graph modes与 Eager 和 Graph 模式无关的 Tensorflow 训练
【发布时间】:2018-07-30 03:12:07
【问题描述】:

我花了一些时间在 Tensorflow 中编写新颖的(我希望的)RNN 单元。 为了原型,我使用渴望模式(更容易调试)。 为了训练,我将代码迁移到图表(运行速度更快)。

我正在寻找一个包装器代码/示例,它可以以一种与我运行它的模式无关的方式运行前向传递和训练 - 尽可能多地渴望或图形。我想到了一组函数/类,可以在其中插入特定的神经网络/优化器/数据,并且这些函数/类集可以在两种模式下运行,而两者之间的变化最小。另外,能兼容多种类型的神经网络/优化器/数据实例当然是好事。

我很确定很多人都有这个想法。 考虑到 TF 中当前的 Eager/Graph 集成,我想知道这样的事情是否可行。

【问题讨论】:

    标签: tensorflow


    【解决方案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 模式又适用于图形模式的代码。

    此外,我敢肯定,对于不那么简单的模型(例如您正在使用的模型),这将变得更加困难。

    【讨论】:

      猜你喜欢
      • 2020-01-03
      • 2019-01-20
      • 2020-09-01
      • 1970-01-01
      • 2022-06-17
      • 1970-01-01
      • 2016-03-09
      • 1970-01-01
      • 2023-03-15
      相关资源
      最近更新 更多