web-dev-qa-db-fra.com

Comment implémenter la segmentation sémantique multi-classes?

Je suis capable de former un U-net avec des images étiquetées qui ont une classification binaire. 

Mais j'ai du mal à comprendre comment configurer les couches finales dans Keras/Theano pour la classification multi-class (4 classes).

J'ai 634 images et 634 masques correspondants qui sont unit8 et 64 x 64 pixels.

Mes masques, au lieu d'être noirs (0) et blancs (1), ont des objets en couleurs étiquetés dans 3 catégories plus l'arrière-plan, comme suit:

  • noir (0), fond
  • rouge (1), classe d'objets 1
  • vert (2), classe d'objets 2
  • jaune (3), classe d'objets 3

Avant la formation, le tableau contenant les masques est codé à chaud, comme suit:

mask_train = to_categorical(mask_train, 4)

Cela fait passer mask_train.shape de (634, 1, 64, 64) à (2596864, 4).

Mon modèle suit de près l'architecture Unet, mais les couches finales semblent problématiques, car je ne parviens pas à aplatir la structure de manière à correspondre au tableau codé à chaud.

[...]
up3 = concatenate([UpSampling2D(size=(2, 2))(conv7), conv2], axis=1)
conv8 = Conv2D(128, (3, 3), activation='relu', padding='same')(up3)
conv8 = Conv2D(128, (3, 3), activation='relu', padding='same')(conv8)

up4 = concatenate([UpSampling2D(size=(2, 2))(conv8), conv1], axis=1)
conv9 = Conv2D(64, (3, 3), activation='relu', padding='same')(up4)
conv10 = Conv2D(64, (3, 3), activation='relu', padding='same')(conv9)

# here I used number classes = number of filters and softmax although
# not sure if a dense layer should be here instead
conv11 = Conv2D(4, (1, 1), activation='softmax')(conv10)

model = Model(inputs=[inputs], outputs=[conv11])

# here categorical cross entropy is being used but may not be correct
model.compile(optimizer='sgd', loss='categorical_crossentropy',
              metrics=['accuracy'])

return model

Avez-vous des suggestions sur la façon de modifier les dernières parties du modèle pour que ce dernier s’entraîne avec succès? Je reçois une variété d’erreurs de disparité de forme, et les quelques fois où j’ai réussi à le faire fonctionner, la perte n’a pas changé au cours des époques.

9
pepe

Vous devriez avoir votre cible sous la forme (634,4,64,64) si vous utilisez channels_first.
Ou (634,64,64,4) si channels_last.

Chaque canal de votre cible devrait être une classe. Chaque canal est une image de 0 et de 1, où 1 signifie que pixel est cette classe et 0 signifie que pixel n'est pas cette classe.

Ensuite, votre cible est 634 groupes, chaque groupe contenant quatre images, chaque image ayant 64x64 pixels, les pixels 1 indiquant la présence de la fonctionnalité souhaitée. 

Je ne suis pas sûr que le résultat sera ordonné correctement, mais vous pouvez essayer:

mask_train = to_categorical(mask_train, 4)
mask_train = mask_train.reshape((634,64,64,4)) 
#I chose channels last here because to_categorical is outputing your classes last: (2596864,4)

#moving the channel:
mask_train = np.moveaxis(mask_train,-1,1)

Si la commande ne fonctionne pas correctement, vous pouvez le faire manuellement:

newMask = np.zeros((634,4,64,64))

for samp in range(len(mask_train)):
    im = mask_train[samp,0]
    for x in range(len(im)):
        row = im[x]
        for y in range(len(row)):
            y_val = row[y]
            newMask[samp,y_val,x,y] = 1
6
Daniel Möller

Un peu tard, mais vous devriez essayer

mask_train = to_categorical(mask_train, num_classes=None)

Cela se traduira par (634, 4, 64, 64) pour mask_train.shape et un masque binaire pour chaque classe individuelle (codé à chaud). 

Dernière couche de conv, l'activation et la perte semblent bonnes pour la segmentation multiclass.

0
Daniel