【问题标题】:How to make tf.data.Dataset.map function executed only once in first epoch?如何使 tf.data.Dataset.map 函数在第一个时期只执行一次?
【发布时间】:2020-09-24 12:37:42
【问题描述】:

我尝试使用 tf.data.Dataset 对数据集进行一些转换。

我发现在每个 epoch 都执行了转换。 map 函数是否可能在第一个 epoch 执行?

【问题讨论】:

    标签: python tensorflow machine-learning keras tensorflow2.0


    【解决方案1】:

    您可以使用不同的数据集。这在自定义训练循环中很容易。就这样:

    def transformation(inputs, labels):
        tf.print('With transformation!')
        return inputs, labels
    
    def no_transformation(inputs, labels):
        tf.print('No transformation!')
        return inputs, labels
    
    data_with_transform = data.take(4).map(transformation).batch(4)
    data_no_transform = data.take(4).map(no_transformation).batch(4)
    

    然后:

    if epoch < 1:
        ds = data_with_transform
    else:
        ds = data_no_transform
    
    for X_train, y_train in ds:
        train_step(X_train, y_train)
    

    完整示例:

    import tensorflow_datasets as tfds
    import tensorflow as tf
    
    data, info = tfds.load('iris', split='train', as_supervised=True,
                           with_info=True)
    
    def transformation(inputs, labels):
        tf.print('With transformation!')
        return inputs, labels
    
    def no_transformation(inputs, labels):
        tf.print('No transformation!')
        return inputs, labels
    
    data_with_transform = data.take(4).map(transformation).batch(4)
    data_no_transform = data.take(4).map(no_transformation).batch(4)
    
    model = tf.keras.Sequential([
        tf.keras.layers.Dense(8, activation='relu'),
        tf.keras.layers.Dense(16, activation='relu'),
        tf.keras.layers.Dense(info.features['label'].num_classes)
    ])
    
    loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
    
    train_loss = tf.keras.metrics.Mean()
    train_acc = tf.keras.metrics.SparseCategoricalAccuracy()
    
    opt = tf.keras.optimizers.Adam(learning_rate=1e-3)
    
    
    @tf.function
    def train_step(inputs, labels):
        with tf.GradientTape() as tape:
            logits = model(inputs)
            loss = loss_object(labels, logits)
    
        gradients = tape.gradient(loss, model.trainable_variables)
        opt.apply_gradients(zip(gradients, model.trainable_variables))
        train_loss(loss)
        train_acc(labels, logits)
    
    
    def main(epochs=5):
    
        for epoch in range(epochs):
    
            train_loss.reset_states()
            train_acc.reset_states()
    
            if epoch < 1:
                ds = data_with_transform
            else:
                ds = data_no_transform
    
            for X_train, y_train in ds:
                train_step(X_train, y_train)
    
    if __name__ == '__main__':
        main()
    
    With transformation!
    With transformation!
    With transformation!
    With transformation!
    
    No transformation!
    No transformation!
    No transformation!
    No transformation!
    
    No transformation!
    No transformation!
    No transformation!
    No transformation!
    
    No transformation!
    No transformation!
    No transformation!
    No transformation!
    
    No transformation!
    No transformation!
    No transformation!
    No transformation!
    

    【讨论】:

    • 非常感谢。这很有帮助。我将以此为指导。
    • 我刚刚仔细阅读了您的解决方案。可能我没有表达清楚。我想要实现的是我想直接使用从第一个时期执行的地图函数获得的转换版本,而不是每个时期都执行地图函数。也就是说,您的解决方案不使用在第一个时期产生的转换。
    • 我不确定我是否理解。您想保存第一个 epoch 的随机变换(即 100 个数据点的 100 个随机变换),并将它们应用到下一个 epoch(即 100 个观察值)?
    • 是的,你知道吗?无论如何,仍然感谢您的详细回答。
    • 好吧,我实际上有一个答案。也许您可以发布一个更简洁地解释它的新问题?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2013-05-22
    • 1970-01-01
    • 2014-07-14
    相关资源
    最近更新 更多