web-dev-qa-db-fra.com

CNN avec keras, la précision ne s'améliore pas

J'ai récemment commencé avec Machine Learning, j'apprends CNN, je prévoyais d'écrire une application pour la détection de la gravité des dommages sur la voiture, à l'aide de ce blog Keras et de ce github repo

Voici à quoi ressemble le jeu de données voiture:

F:\WORKSPACE\ML\CAR_DAMAGE_DETECTOR\DATASET\DATA3A
├───training (979 Images for all 3 categories of training set)
│   ├───01-minor
│   ├───02-moderate
│   └───03-severe
└───validation (171 Images for all 3 categories of validation set)
    ├───01-minor
    ├───02-moderate
    └───03-severe

Le code suivant ne me donne que 32% de précision.

from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras import backend as K


# dimensions of our images.
img_width, img_height = 150, 150

train_data_dir = 'dataset/data3a/training'
validation_data_dir = 'dataset/data3a/validation'
nb_train_samples = 979
nb_validation_samples = 171
epochs = 10
batch_size = 16

if K.image_data_format() == 'channels_first':
    input_shape = (3, img_width, img_height)
else:
    input_shape = (img_width, img_height, 3)

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
    rescale=1. / 255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1. / 255)

train_generator = train_datagen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height),
    batch_size=batch_size,
    class_mode='binary')
model.fit_generator(
    train_generator,
    steps_per_Epoch=nb_train_samples // batch_size,
    epochs=epochs,
    validation_data=validation_generator,
    validation_steps=nb_validation_samples // batch_size)

model.save_weights('first_try.h5')

J'ai essayé:

  • En augmentant les époques à 10, 20,50.
  • En augmentant les images dans le jeu de données (toutes les images de validation ajoutées au jeu d'apprentissage).
  • En mettant à jour la taille du filtre dans la couche Conv2D
  • J'ai essayé d'ajouter deux couches Conv2D, MaxPooling
  • Également essayé avec différents optimiseurs tels que adam, Sgd, etc.
  • Aussi essayé en mettant à jour les étapes du filtre à (1,1) and (5,5) au lieu de (3,3)
  • Également essayé en mettant à jour les dimensions changeantes de l'image à (256, 256), (64, 64) à partir de (150, 150) 

Mais pas de chance, chaque fois que j'obtiens une précision de 32% ou moins, mais pas plus… .. Toute idée de ce qui me manque.

Comme dans le github repo que nous pouvons voir, cela donne une précision de 72% pour le même jeu de données (Training -979, Validation -171). Pourquoi ça ne marche pas pour moi.

J'ai essayé son code à partir du lien github sur ma machine, mais celui-ci s'est accroché pendant l'entraînement du jeu de données (j'ai attendu plus de 8 heures), donc j'ai changé d'approche, mais toujours pas de chance jusqu'à présent.

Voici la sortie contenant Pastebin de mes époques d’entraînement.

5
Laxmikant

Le problème est dû à une mauvaise correspondance entre le nombre de classes de sortie (trois) et le choix de l'activation de la couche finale (sigmoïde) et de la fonction de perte (entropie croisée binaire).

La fonction sigmoïde "écrase" les valeurs réelles dans une valeur comprise entre [0, 1], mais elle est conçue uniquement pour les problèmes binaires (à deux classes). Pour plusieurs classes, vous devez utiliser quelque chose comme la fonction softmax. Softmax est une version généralisée de sigmoid (les deux devraient être équivalents lorsque vous avez deux classes).

La valeur de perte doit également être mise à jour pour prendre en charge une classe pouvant gérer plusieurs classes - l'entropie croisée catégorique fonctionnera dans ce cas.

En termes de code, si vous modifiez la définition du modèle et le code de compilation à la version ci-dessous, cela devrait fonctionner.

model = Sequential()
model.add(Conv2D(32, (3, 3), input_shape=input_shape))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

Enfin, vous devez spécifier class_mode='categorical' dans vos générateurs de données. Cela garantira que les cibles de sortie sont formatées en tant que matrice catégorielle à trois colonnes, avec un dans la colonne correspondant à la valeur correcte et des zéros ailleurs. Ce format de réponse est requis par la fonction de perte categorical_cross_entropy.

5
SymbolixAU

Correction mineure: 

model.add(Dense(1))

Devrait être:

model.add(Dense(3))

Il doit être conforme au nombre de classes dans la sortie. 

1
satyanarayan rao