微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在Keras model.fit中使用tf.Dataset而不指定目标?

如何解决如何在Keras model.fit中使用tf.Dataset而不指定目标?

我想使用带有Keras功能API的AutoEncoder模型。我也想使用tf.data.Dataset作为模型的输入管道。但是,有一个限制,我只能将元组keras.model.fit附加到docs的情况下将数据集传递到(inputs,targets)

输入数据。可能是:tf.data数据集。应该返回(输入,目标)或(输入,目标,sample_weights)的元组

这是一个问题:我可以通过tf.data.Dataset而不重复类似(inputs,inputs)之类的输入吗?如果我做不到,那么重复输入是否会使我的模型的GPU内存增加一倍?

解决方法

您可以使用map()返回两次输入:

import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import tensorflow as tf
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Conv2D,MaxPool2D,Conv2DTranspose,Reshape
from functools import partial

(xtrain,_),(xtest,_) = tf.keras.datasets.mnist.load_data()

ds = tf.data.Dataset.from_tensor_slices(
    tf.expand_dims(tf.concat([xtrain,xtest],axis=0),axis=-1))

ds = ds.take(int(1e4)).batch(4).map(lambda x: (x/255,x/255))

custom_convolution = partial(Conv2D,kernel_size=(3,3),strides=(1,1),activation='relu',padding='same')
custom_pooling = partial(MaxPool2D,pool_size=(2,2))

conv_encoder = Sequential([
    custom_convolution(filters=16,input_shape=(28,28,1)),custom_pooling(),custom_convolution(filters=32),custom_convolution(filters=64),custom_pooling()
    ])

# conv_encoder(next(iter(ds))[0].numpy().astype(float)).shape
custom_transpose = partial(Conv2DTranspose,padding='same',strides=(2,2))

conv_decoder = Sequential([
    custom_transpose(filters=32,input_shape=(3,3,64),padding='valid'),custom_transpose(filters=16),custom_transpose(filters=1,activation='sigmoid'),Reshape(target_shape=[28,1])
    ])

conv_autoencoder = Sequential([
    conv_encoder,conv_decoder
    ])

conv_autoencoder.compile(loss='binary_crossentropy',optimizer='adam')

history = conv_autoencoder.fit(ds)
2436/2500 [============================>.] - ETA: 0s - loss: 0.1282
2446/2500 [============================>.] - ETA: 0s - loss: 0.1280
2456/2500 [============================>.] - ETA: 0s - loss: 0.1279
2466/2500 [============================>.] - ETA: 0s - loss: 0.1278
2476/2500 [============================>.] - ETA: 0s - loss: 0.1277
2487/2500 [============================>.] - ETA: 0s - loss: 0.1275
2497/2500 [============================>.] - ETA: 0s - loss: 0.1274
2500/2500 [==============================] - 14s 6ms/step - loss: 0.1273
,

“重复的输入使我的模型的GPU内存增加了一倍?”;通常,数据集管道在CPU上运行,而不是在GPU上运行。

对于AutoEncoder模型,如果要使用仅包含示例而不包含标签的数据集,则可以使用自定义训练:

def loss(model,x):

    y_ = model(x,training=True)           # use x as input

   return loss_object(y_true=x,y_pred=y_) # use x as label (y_true)

with tf.GradientTape() as tape:
   loss_value = loss(model,inputs)

如果有必要使用fit()方法,则可以将keras.Model子类化,并覆盖train_step()方法 link 。 (我没有验证此代码):

class CustomModel(keras.Model):
def train_step(self,data):

    x = data
    y = data  # the same data as label ++++

    with tf.GradientTape() as tape:
        y_pred = self(x,training=True)  # Forward pass
      
        loss = self.compiled_loss(y,y_pred,regularization_losses=self.losses)

    # Compute gradients
    trainable_vars = self.trainable_variables
    gradients = tape.gradient(loss,trainable_vars)
    # Update weights
    self.optimizer.apply_gradients(zip(gradients,trainable_vars))
    # Update metrics (includes the metric that tracks the loss)
    self.compiled_metrics.update_state(y,y_pred)
    # Return a dict mapping metric names to current value
    return {m.name: m.result() for m in self.metrics}
,

在 TensorFlow 2.4 中,我有一个数据集,它返回一个元素的元组,即 (inputs,),这是训练很好。唯一的警告当然是您不能将损失或指标传递给 model.compile,而必须在模型中的某处使用 add_lossadd_metric API。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。