web-dev-qa-db-fra.com

from_logits = True et from_logits = False obtiennent des résultats d'entraînement différents pour tf.losses.CategoricalCrossentropy for UNet

Je fais le travail de segmentation sémantique d'image avec unet, si je définis le Softmax Activation Pour le dernier calque comme ceci:

...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
conv10 = (Activation('softmax'))(conv9)
model = Model(inputs, conv10)
return model
...

puis en utilisant loss = tf.keras.losses.CategoricalCrossentropy(from_logits=False) La formation ne convergera pas même pour une seule image de formation.

Mais si je ne règle pas le Softmax Activation Pour la dernière couche comme ceci:

...
conv9 = Conv2D(n_classes, (3,3), padding = 'same')(conv9)
model = Model(inputs, conv9)
return model
...

puis en utilisant loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True) La formation convergera pour une image de formation.

Mon jeu de données Groundtruth est généré comme ceci:

X = []
Y = []
im = cv2.imread(impath)
X.append(im)
seg_labels = np.zeros((height, width, n_classes))
for spath in segpaths:
    mask = cv2.imread(spath, 0)
    seg_labels[:, :, c] += mask
Y.append(seg_labels.reshape(width*height, n_classes))

Pourquoi? Y a-t-il un problème avec mon utilisation?

Voici mon code d'expérience de git: https://github.com/honeytidy/unet Vous pouvez commander et exécuter (peut s'exécuter sur cpu). Vous pouvez changer la couche d'activation et from_logits de CategoricalCrossentropy et voir ce que j'ai dit.

8
tidy

Pousser l'activation "softmax" dans la couche de perte d'entropie croisée simplifie considérablement le calcul de perte et le rend plus stable numériquement.
Il se peut que dans votre exemple, les problèmes numériques soient suffisamment importants pour rendre le processus de formation inefficace pour le from_logits=False option.

Vous pouvez trouver une dérivation de la perte d'entropie croisée (un cas spécial de perte de "gain d'information") dans ce post . Cette dérivation illustre les problèmes numériques qui sont évités lors de la combinaison de softmax avec la perte d'entropie croisée.

5
Shai

Je suppose que le problème vient de la fonction d'activation softmax. En regardant le doc j'ai trouvé que sotmax est appliqué au dernier axe par défaut. Pouvez-vous regarder model.summary() et vérifier si c'est ce que vous voulez?

0
Simon Delecourt

Pour que softmax fonctionne correctement, vous devez vous assurer que:

  • Vous utilisez 'channels_last' Comme configuration de canal par défaut Keras.

    • Cela signifie que les formes du modèle seront comme (None, height, width, channels)
    • Cela semble être votre cas car vous placez n_classes Dans le dernier axe. Mais c'est aussi étrange car vous utilisez Conv2D Et votre sortie Y devrait être (1, height, width, n_classes) Et non pas la forme étrange que vous utilisez.
  • Votre Y n'a que des zéros et des uns (pas 0 et 255 comme cela arrive habituellement aux images)

    • Vérifiez que Y.max() == 1 et Y.min() == 0
    • Vous devrez peut-être avoir Y = Y / 255.
  • Une seule classe est correcte (vos données n'ont pas plus d'un chemin/canal avec une valeur = 1).

    • Vérifiez que (Y.sum(axis=-1) == 1).all() Est True
0
Daniel Möller