Потери в мульти-входной модели Keras резко упали - PullRequest
0 голосов
/ 08 февраля 2019

При использовании модели с несколькими входами keras, модель просто не тренируется вообще.Точность возрастает почти до 100%, а потери стремительно падают, поэтому я думаю, что что-то не так с генерацией данных.

Я использую модель керас с несколькими входами, с двумя изображениями одного и того же объекта, только что повернутыми.План состоит в том, чтобы провести каждое изображение через его собственный CNN, затем объединить два сплющенных слоя и классифицировать объект.

Я подготавливаю данные, используя найденный метод (здесь) [https://github.com/keras-team/keras/issues/8130]. Изображения находятся в отдельных каталогах, но с одинаковым заполнением, они загружаются правильно.Метки тоже правильные, я проверил, посмотрев на имена файлов и каталоги, которые генерирует ImageDataGenerator.

Модель достаточно проста, я не думаю, что это вызывает проблему

def multiInput_model():
    #create model - custom

    input_1 = Input(shape=(img_width,img_height,1))
    input_2 = Input(shape=(img_width,img_height,1))   

    output_1 = Conv2D(32,(5,5), activation='relu')(input_1)
    output_1 = BatchNormalization()(output_1)
    output_1 = MaxPooling2D(pool_size=(2,2))(output_1)
    output_1 = Dropout(0.4)(output_1)
    output_1 = Flatten()(output_1)

    output_2 = Conv2D(32,(5,5), activation='relu')(input_2)
    output_2 = BatchNormalization()(output_2)
    output_2 = MaxPooling2D(pool_size=(2,2))(output_2)
    output_2 = Dropout(0.4)(output_2)
    output_2 = Flatten()(output_2)

    inputs = [input_1,input_2]
    outputs = [output_1,output_2]
    combine = concatenate(outputs)

    output = Dense(32,activation='relu')(combine)
    output = Dense(num_classes,activation='softmax')(output)


    model = Model(inputs,[output])


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

    return model

Генераторы изображений следующие

def generate_generator_multiple(generator,dir1, dir2, batch_size, img_width,img_height,subset):
    genX1 = generator.flow_from_directory(dir1,
                                      color_mode='grayscale',
                                      target_size= 
                                      (img_width,img_height),
                                      batch_size=batch_size,
                                      class_mode='categorical',
                                      shuffle=False,
                                      subset=subset,
                                      seed=1)
                                      #Same seed for consistency.

    genX2 = generator.flow_from_directory(dir2,
                                      color_mode='grayscale',
                                      target_size= 
                                      (img_width,img_height),
                                      batch_size=batch_size,
                                      class_mode='categorical',
                                      shuffle=False,
                                      subset=subset,
                                      seed=1)
    while True:
        X1i = genX1.next()
        X2i = genX2.next()
        yield [X1i[0],X2i[0]],X1i[1]    #Yields both images and their mutual label



train_generator = 
generate_generator_multiple(generator=train_datagen,
                                          dir1=train_data_dirA,
                                          dir2=train_data_dirB,
                                          batch_size=batch_size,
                                          img_width=img_width,
                                          img_height=img_height,
                                          subset='training')

validation_generator =  
generate_generator_multiple(generator=train_datagen,
                                               dir1=train_data_dirA,
                                               dir2=train_data_dirB,
                                               batch_size=batch_size,
                                               img_width=img_width,
                                               img_height=img_height,
                                               subset='validation')

Выход всегда такойэто

20/20 [==============================] - 4s 183ms/step - loss: 0.1342 - acc: 0.9500 - val_loss: 1.1921e-07 - val_acc: 1.0000
Epoch 2/20
20/20 [==============================] - 0s 22ms/step - loss: 1.1921e-07 - acc: 1.0000 - val_loss: 8.0590 - val_acc: 0.5000
Epoch 3/20
20/20 [==============================] - 0s 22ms/step - loss: 1.1921e-07 - acc: 1.0000 - val_loss: 16.1181 - val_acc: 0.0000e+00
Epoch 4/20
20/20 [==============================] - 0s 22ms/step - loss: 8.0590 - acc: 0.5000 - val_loss: 16.1181 - val_acc: 0.0000e+00

РЕДАКТИРОВАТЬ : Хорошо, алгоритм немного тренируется.Точность, кажется, улучшается, но точность проверки остается на уровне 0,111 (что составляет 1/9, что означает, что сеть просто угадывает метку изображения).Тем не менее, точность обучения улучшается, поэтому, по крайней мере, это переобучение (на данный момент).

EDIT2 : я вручную отредактировал каталоги так, что я больше не использую подмножество.Каталоги разделены следующим образом:

-dir1 -> train -> class1 -> img...
               -> class2 -> img...
                ....
               -> class9 -> img...
      -> validate -> class1 -> img...
                  -> class2 -> img...
                  ....
                  -> class9 -> img...

-dir2 -> train -> class1 -> img...
               -> class2 -> img...
                ....
               -> class9 -> img...
      -> validate -> class1 -> img...
                  -> class2 -> img...
                  ....
                  -> class9 -> img...

Более интересным моментом является то, что потеря проверки увеличивается, а потеря обучения уменьшается.Начиная с 4 эпох, это результаты

126/126 [==============================] - 92s 730ms/step - loss: 
1.7158 - acc: 0.6583 - val_loss: 4.4013 - val_acc: 0.1111
Epoch 2/20
126/126 [==============================] - 88s 698ms/step - loss: 
1.2179 - acc: 0.7859 - val_loss: 5.5854 - val_acc: 0.1111
Epoch 3/20
126/126 [==============================] - 88s 700ms/step - loss: 
0.9849 - acc: 0.8308 - val_loss: 6.2045 - val_acc: 0.1111
Epoch 4/20
126/126 [==============================] - 89s 705ms/step - loss: 
0.9357 - acc: 0.8513 - val_loss: 6.9400 - val_acc: 0.1111

Обновление Проверены пары изображений и метки изображений.Все метки для изображений правильные.Все изображения правильно спарены.

Ответы [ 2 ]

0 голосов
/ 11 февраля 2019

Не совсем ответ, но мой вопрос содержит слишком много обновлений:

Прежде всего, я обнаружил, что, установив shuffle = False, он не тренировался.Изменяя shuffle = true, некоторые результаты на самом деле стали известны!

Во-вторых, модель была недостаточно глубокой.Добавление еще одного сверточного слоя (или двух) помогло значительно.

Почему помогло значение shuffle = True?Я думаю, это потому, что если все данные проходят через сеть одним и тем же способом, одинаковым образом каждый раз, это неизбежно приводит к плохой тренировке, поскольку это не вносит большой разброс в модель.Установив shuffle = True и одинаковое начальное число для обоих случаев, это означало, что количество перемешивания будет одинаковым (следовательно, изображения будут по-прежнему правильно соединены), но порядок их прохождения по сети отличается.

Если кто-то может добавить дополнительную информацию, пожалуйста.

0 голосов
/ 08 февраля 2019

Низкие потери при обучении и высокие потери в валу обычно указывают на переобучение.

в этом случае может оказаться, что выходной сигнал первого конвон-слоя слишком велик для подачи в плотный слой, что приводит кматрица огромных весов внутри плотного слоя, который перекрывает данные.

возможно, наложение более Conv2d + MaxPooling2d слоев уменьшит входной размер до плотного слоя и приведет к уменьшению общего количествапараметры в нейронной сети, помогающие вам справиться с обмундированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...