Le classificateur d'image multi-classe Train à Keras

je suivais un tutoriel pour apprendre à former un classificateur en utilisant Keras

https://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html

spécifiquement, de la deuxième script donné par l'auteur, je voulais transformer le script en un qui peut former classifier multi-classe(était un binaire pour chat et chien). J'ai 5 classes dans mon dossier train donc j'ai fait le changement suivant:

en fonction de train_top_model ():

j'ai changé

model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:]))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))

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

en

model = Sequential()
model.add(Flatten(input_shape=train_data.shape[1:]))
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(5, activation='sigmoid'))

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

train_labels = to_categorical(train_labels, 5)
validation_labels = to_categorical(validation_labels, 5)

après avoir effectué la formation, le modèle a atteint une précision d'entraînement de près de 99%, mais seulement pour une précision d'environ 70% de la précision de validation. J'ai donc commencé à penser qu'il n'était peut-être pas si simple de convertir 2 classes de formation en 5 classes. Peut-être que j'ai besoin d'utiliser l'encodage one-hot lors de l'étiquetage des classes(mais je ne sais pas comment faire)

EDIT:

j'ai joint aussi mon scénario. Un autre problème: la précision n'augmente pas de manière efficace lorsque le réglage fin commence.

import os
import h5py
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.layers import Activation, Dropout, Flatten, Dense

# path to the model weights files.
weights_path = 'D:/Users/EJLTZ/Desktop/vgg16_weights.h5'
top_model_weights_path = 'bottleneck_weights_2.h5'
# dimensions of our images.
img_width, img_height = 150, 150

train_data_dir = 'D:/Users/EJLTZ/Desktop/BodyPart-full/train_new'
validation_data_dir = 'D:/Users/EJLTZ/Desktop/BodyPart-full/validation_new'
nb_train_samples = 500
nb_validation_samples = 972
nb_epoch = 50

# build the VGG16 network
model = Sequential()
model.add(ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height)))

model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))

# load the weights of the VGG16 networks
# (trained on ImageNet, won the ILSVRC competition in 2014)
# note: when there is a complete match between your model definition
# and your weight savefile, you can simply call model.load_weights(filename)
assert os.path.exists(weights_path), 'Model weights not found (see "weights_path" variable in script).'
f = h5py.File(weights_path)
for k in range(f.attrs['nb_layers']):
    if k >= len(model.layers):
        # we don't look at the last (fully-connected) layers in the savefile
        break
    g = f['layer_{}'.format(k)]
    weights = [g['param_{}'.format(p)] for p in range(g.attrs['nb_params'])]
    model.layers[k].set_weights(weights)
f.close()
print('Model loaded.')

# build a classifier model to put on top of the convolutional model
top_model = Sequential()
top_model.add(Flatten(input_shape=model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(5, activation='softmax'))

# note that it is necessary to start with a fully-trained
# classifier, including the top classifier,
# in order to successfully do fine-tuning
top_model.load_weights(top_model_weights_path)

# add the model on top of the convolutional base
model.add(top_model)

# set the first 25 layers (up to the last conv block)
# to non-trainable (weights will not be updated)
for layer in model.layers[:25]:
    layer.trainable = False

# compile the model with a SGD/momentum optimizer
# and a very slow learning rate.
model.compile(loss='categorical_crossentropy',
          optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
          metrics=['accuracy'])

# prepare data augmentation configuration
train_datagen = ImageDataGenerator(
    rescale=1./255,
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True)

test_datagen = ImageDataGenerator(rescale=1./255)

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

validation_generator = test_datagen.flow_from_directory(
    validation_data_dir,
    target_size=(img_height, img_width),
    batch_size=32,
    class_mode= 'categorical')

# fine-tune the model
model.fit_generator(
    train_generator,
    samples_per_epoch=nb_train_samples,
    nb_epoch=nb_epoch,
    validation_data=validation_generator,
    nb_val_samples=nb_validation_samples)

model.save_weights("fine-tune_weights.h5")
model.save("fine-tune_model.h5", True)
11
demandé sur Austin Chen 2017-01-24 11:12:06

1 réponses

  1. Utiliser softmax comme fonction d'activation de la couche de sortie, c'est une généralisation de la fonction logistique pour un cas multi-classes. Lire plus sur le sujet ici.

  2. Si erreur de validation est beaucoup plus grande que la formation, comme dans votre cas, c'est un indicateur de surapprentissage. Vous devez faire une régularisation, qui est défini comme tout changement de l'algorithme d'apprentissage, qui sont destinés à réduire l'erreur de test, mais pas la formation un. Vous pouvez essayer des choses comme l'augmentation des données, l'arrêt précoce, l'injection de bruit, le décrochage plus agressif, etc.

  3. si vous avez la même configuration que dans le tutoriel lié, changez le class_modetrain_generatoret validation_generatorcategorical et il sera un chaud-encoder vos classes.

13
répondu Sergii Gryshkevych 2017-06-28 05:43:44