如何在不指定目标的情况下在Keras model.fit中使用tf.Dataset



我想使用具有Keras功能的API的AutoEncoder模型。此外,我还想使用tf.data.Dataset作为模型的输入管道。然而,有一个限制,我只能将数据集传递给keras.model.fit,其中元组(inputs, targets)对应于文档:

输入数据。它可能是:一个tf.data数据集。应返回(inputs,target(或(inputs、target、sample_weights(的元组。

所以问题来了:我可以在不重复(inputs, inputs)(inputs, None)之类的输入的情况下传递tf.data.Dataset吗。如果我做不到,重复输入会使我的模型的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_pooling(),
custom_convolution(filters=64),
custom_pooling()
])
# conv_encoder(next(iter(ds))[0].numpy().astype(float)).shape
custom_transpose = partial(Conv2DTranspose,
padding='same',
kernel_size=(3, 3),
activation='relu',
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, 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子类化。建模并覆盖train_step((方法链接。(我没有验证这个代码(:

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_metricAPI。

相关内容

最新更新