2
votes

Problèmes d'utilisation de l'API Tensorflow Datasets avec Keras

J'essaie d'adapter un modèle CNN Keras, en l'alimentant avec des données gérées par l'API Datasets de Tensorflow. Cependant, je trébuche encore et encore sur la même exception, malgré la documentation officielle (voir ):

test_data, train_data = tfds.load("mnist", split=Split.ALL.subsplit([1, 3]))

# [...] Images are normalized using Dataset.map method
# [...] Labels are converted into one-hot encodings as well, using tf.one_hot function

model = keras.Sequential([
    keras.layers.Conv2D(
        32,
        kernel_size=5,
        padding="same",
        input_shape=(28, 28, 1),
        activation="relu",
    ),
    keras.layers.MaxPooling2D(
        (2, 2),
        padding="same"
    ),
    keras.layers.Conv2D(
        64,
        kernel_size=5,
        padding="same",
        activation="relu"
    ),
    keras.layers.MaxPooling2D(
        (2, 2),
        padding="same"
    ),
    keras.layers.Flatten(),
    keras.layers.Dense(
        512,
        activation="relu"
    ),
    keras.layers.Dropout(rate=0.4),
    keras.layers.Dense(10, activation="softmax")
])

model.compile(
    optimizer=tf.train.AdamOptimizer(0.01),
    loss="categorical_crossentropy",
    metrics=["accuracy"]
)

train_data = train_data.batch(32).repeat()
test_data = test_data.batch(32).repeat()

model.fit(
    train_data,
    epochs=10,
    steps_per_epoch=30,
    validation_data=test_data,
    validation_steps=3
) # The exception occurs at this step

J'utilise l'ensemble de données MNIST de tensorflow-datasets , les images sont normalisées et les étiquettes de classe sont converties en encodages one-hot. Vous pouvez voir un extrait du code ci-dessous.

ValueError: No data provided for "conv2d_8_input". Need data for each key in: ['conv2d_8_input']
# conv2d_8 is the first Conv2D layer of my model, see below

Je ne comprends pas pourquoi cela ne fonctionne pas, j'ai essayé d'alimenter la méthode fit avec des itérateurs one-shot au lieu de les ensembles de données, mais j'obtiens le même résultat. Je ne suis pas habitué à Keras et TensorFlow (je travaille généralement avec PyTorch), donc je pense qu'il me manque peut-être quelque chose d'évident.


4 commentaires

Le jeu de données MNIST est d'une forme différente de 28,28,1. Avez-vous un remodelage quelque part avant le premier conv2d? Par exemple, reportez-vous à tensorflow.org/tutorials/estimators/cnn


@Prabindh bien, on dirait que la forme est bien (28,28,1). Un print (train_data) juste avant model.fit (...) donne la sortie suivante: . (La première dimension inconnue est la dimension du lot.)


Je suppose que l'ensemble de données est cassé. Avez-vous testé s'il est non vide / ne renvoie pas simplement Aucun ?


@ xdurch0 Je suis en mesure de récupérer des données valides du jeu de données (avec un itérateur en une seule fois) et d'afficher les images et les étiquettes correspondantes dans un pyplot.


3 Réponses :


1
votes

Ok, je l'ai. J'ai activé une exécution impatiente pour voir si Keras donnerait une exception plus précise, et j'ai obtenu ceci:

train_data = train_data.map(lambda x: tuple(x.values()))
test_data = test_data.map(lambda x: tuple(x.values()))

En effet, les composants de mes ensembles de données (images et leurs étiquettes associées) ont des noms ("image "et" label "), car c'est ainsi que tensorflow_datasets les charge. En conséquence, un itérateur sur les ensembles de données produit un dictionnaire avec deux valeurs: "image" et "label".

Cependant, Keras attend un tuple de deux valeurs (entrées, cibles) (ou trois valeurs ( entrées, cibles, sample_wheights) ), et il n'aime pas le dictionnaire produit par l'itérateur de l'ensemble de données (d'où l'erreur que j'ai obtenue).

J'ai ajouté le code suivant avant le modèle .fit :

ValueError: Output of generator should be a tuple `(x, y, sample_weight)` or `(x, y)`. Found: {'image': <tf.Tensor: id=1012, shape=(32, 28, 28, 1), dtype=float64, numpy=array([...])>, 'label': <tf.Tensor: id=1013, shape=(32, 10), dtype=uint8, numpy=array([...]), dtype=uint8)>}

Et ça marche.


3 commentaires

Je n'aime pas cette solution pour être honnête, elle ne semble pas propre. Cependant, c'est la seule solution de contournement que j'ai trouvée pour atténuer cette limitation de Keras.


Si vous utilisez la version TF de keras, cela ne devrait idéalement pas être requis. Voir github.com/tensorflow/tensorflow/issues/20698


@Prabindh Je ne suis pas sûr que cela soit entièrement lié, car je n'ai pas de modèle multi-entrées? Dois-je quand même mentionner mon cas sur le problème de github?



1
votes

Vous pouvez charger des données depuis tensorflow-datasets directement sous forme de tuple en utilisant as_supervised

test_data, train_data = tfds.load("mnist", split=tfds.Split.ALL.subsplit([1, 3]), as_supervised=True)


0 commentaires

3
votes

Pour ceux qui viennent sur cette page après avoir suivi le tutoriel TF 2.0 Beta sur le chargement d'images ( https : //www.tensorflow.org/beta/tutorials/load_data/images ):

J'ai pu éviter l'erreur en renvoyant un tuple dans la fonction preprocess_image

def preprocess_image(image):
image = tf.image.decode_jpeg(image, channels=3)
image = tf.image.resize(image, [192, 192])
image /= 255.0  # normalize to [0,1] range
return (image,image)


0 commentaires