J'essaie d'entraîner un réseau neuronal créé avec l'API Keras Functional avec l'un des ensembles de données TFDS par défaut, mais je continue à obtenir des erreurs liées à l'ensemble de données.
L'idée est de faire un modèle pour la détection d'objets, mais pour la première version, j'ai essayé de faire une simple classification d'images (img, label). L'entrée serait des images (256x256x3). La couche d'entrée est la suivante :
img_inputs = keras.Input(shape=[256, 256, 3], name='image')
J'essaie ensuite d'utiliser l'ensemble de données voc2007 tel qu'il est disponible dans TFDS (une version très ancienne et légère pour accélérer le processus).
(train_ds, test_ds), ds_info = tfds.load(
'voc/2007',
split=['train', 'test'],
data_dir="/content/drive/My Drive",
with_info=True)
puis de prétraiter les données comme suit :
def resize_and_normalize_img(example):
"""Normalizes images: `uint8` -> `float32`."""
example['image'] = tf.image.resize(example['image'], [256, 256])
example['image'] = tf.cast(example['image'], tf.float32) / 255.
return example
def reduce_for_classification(example):
for key in ['image/filename', 'labels_no_difficult', 'objects']:
example.pop(key)
return example
train_ds_class = train_ds.map(reduce_for_classification, num_parallel_calls=tf.data.AUTOTUNE)
train_ds_class = train_ds_class.map(resize_and_normalize_img, num_parallel_calls=tf.data.AUTOTUNE)
train_ds_class = train_ds_class.cache()
train_ds_class = train_ds_class.shuffle(ds_info.splits['train'].num_examples)
train_ds_class = train_ds_class.batch(64)
train_ds_class = train_ds_class.prefetch(tf.data.AUTOTUNE)
test_ds_class = test_ds.map(reduce_for_classification, num_parallel_calls=tf.data.AUTOTUNE)
test_ds_class = test_ds_class.map(resize_and_normalize_img, num_parallel_calls=tf.data.AUTOTUNE)
test_ds_class = test_ds_class.batch(64)
test_ds_class = test_ds_class.cache()
test_ds_class = test_ds_class.prefetch(tf.data.AUTOTUNE)
Et puis on ajuste le modèle comme :
epochs=8
history = model.fit(
x=train_x, y =trian_y,
validation_data=test_ds_clas,
epochs=epochs
)
Après avoir fait cela, je reçois une erreur disant que mon modèle attend une entrée de forme [None, 256, 256, 3] mais il reçoit une entrée de forme [256, 256, 3].
Je pense que c'est un problème lié à l'étiquette. Avant, j'ai eu des problèmes avec les clés supplémentaires du format de type dictionnaire des données que vous obtenez de tfds et j'ai essayé de tout supprimer sauf le label, mais maintenant j'ai toujours ce problème et je ne sais pas comment avancer. J'ai l'impression qu'après avoir préparé le jeu de données avec tfds, il devrait être prêt à être alimenté par un modèle, et après avoir parcouru la documentation, les tutoriels et stack overflow, je n'ai pas trouvé la réponse, j'espère que quelqu'un qui rencontrera ce problème pourra m'aider.
Mise à jour : Pour donner un peu plus d'informations, voici le modèle que j'utilise :
TLDR : Entrée de l'image 256x256x3, une succession de convolutions et de blocs résiduels, et une fin avec mise en commun des moyennes, couche entièrement connectée, et softmax qui aboutit à un tenseur (None, 1280). Utilisation de l'entropie croisée catégorielle éparse comme perte et de la précision comme métrique.
img_inputs = keras.Input(shape=[256, 256, 3], name='image')
# first convolution
conv_first = tf.keras.layers.Conv2D(32, kernel_size=(3, 3), padding='same', name='first_conv')
x = conv_first(img_inputs)
# Second convolution
x = tf.keras.layers.Conv2D(64, kernel_size=(3, 3), strides=2, padding='same', name='second_conv')(x)
# First residual block
res = tf.keras.layers.Conv2D(32, kernel_size=(1, 1), name='res_block1_conv1')(x)
res = tf.keras.layers.Conv2D(64, kernel_size=(3, 3), padding='same', name='res_block1_conv2')(res)
x = x + res
# Convolution after First residual block
x = tf.keras.layers.Conv2D(128, kernel_size=3, strides=2, padding='same', name='first_post_res_conv')(x)
# Second residual Block
for i in range(2):
shortcut = x
res = tf.keras.layers.Conv2D(64, kernel_size=1, name=f'res_block2_conv1_loop{i}')(x)
res = tf.keras.layers.Conv2D(128, kernel_size=3, padding='same', name=f'res_block2_conv2_loop{i}')(res)
x = res + shortcut
# Convolution after Second residual block
x = tf.keras.layers.Conv2D(256, 3, strides=2, padding='same', name='second_post_res_conv')(x)
# Third residual Block
for i in range(8):
shortcut = x
res = tf.keras.layers.Conv2D(128, kernel_size=1, name=f'res_block3_conv1_loop{i}')(x)
res = tf.keras.layers.Conv2D(256, kernel_size=3, padding='same', name=f'res_block3_conv2_loop{i}')(res)
x = res + shortcut
# Convolution after Third residual block
x = tf.keras.layers.Conv2D(512, 3, strides=2, padding='same', name='third_post_res_conv')(x)
# Fourth residual Block
for i in range(8):
shortcut = x
res = tf.keras.layers.Conv2D(256, kernel_size=1, name=f'res_block4_conv1_loop{i}')(x)
res = tf.keras.layers.Conv2D(512, kernel_size=3, padding='same', name=f'res_block4_conv2_loop{i}')(res)
x = res + shortcut
# Convolution after Fourth residual block
x = tf.keras.layers.Conv2D(1024, 3, strides=2, padding='same', name='fourth_post_res_conv')(x)
# Fifth residual Block
for i in range(4):
shortcut = x
res = tf.keras.layers.Conv2D(512, kernel_size=1, name=f'res_block5_conv1_loop{i}')(x)
res = tf.keras.layers.Conv2D(1024, kernel_size=3, padding='same', name=f'res_block5_conv2_loop{i}')(res)
x = res + shortcut
# Global avg pooling
x = tf.keras.layers.GlobalAveragePooling2D(name='average_pooling')(x)
# Fully connected layer
x = tf.keras.layers.Dense(1280, name='fully_connected_layer')(x)
# Softmax
end_result = tf.keras.layers.Softmax(name='softmax')(x)
model = tf.keras.Model(inputs=img_inputs, outputs=end_result, name="darknet53")
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
Après avoir essayé la solution proposée par AloneTogether, j'obtiens les erreurs suivantes (j'ai essayé de changer l'axe dans la fonction tf.one_hot() plusieurs fois et même résultat) :
Node: 'sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits'
logits and labels must have the same first dimension, got logits shape [64,1280] and labels shape [1280]
[[{{node sparse_categorical_crossentropy/SparseSoftmaxCrossEntropyWithLogits/SparseSoftmaxCrossEntropyWithLogits}}]] [Op:__inference_train_function_20172]
Ce qui semble être lié à la mise en lot, mais je ne sais pas exactement comment le résoudre.
Le problème semble vraiment lié à l'encodage des étiquettes, car en exécutant cette ligne sans la fonction tf.reduce_sum(), j'obtiens le même résultat, mais avec :
First element had shape [2,20] and element 1 had shape [1,20].
Et si j'exécute la même chose sans la ligne d'encodage à un coup, j'obtiens cette erreur :
''' Node : IteratorGetNext Impossible de regrouper des tenseurs avec des formes différentes dans l'élément 1. Le premier élément avait la forme [4] et l'élément 1 avait la forme [1]. [[{{node IteratorGetNext}}]] [Op:__inference_train_function_18534] '''