Keras多输入模型损失骤降,无法训练

时间:2019-02-08 13:39:45

标签: python keras

虽然使用keras的多输入模型,但是该模型根本不训练。准确率飙升至接近100%,损失骤降,因此我认为数据生成存在问题。

我使用的是多输入keras模型,只是旋转了同一对象的两个图像。计划是通过其自己的CNN运行每个图像,然后连接两个平坦的层并对对象进行分类。

我使用找到的方法(这里)[https://github.com/keras-team/keras/issues/8130]准备数据。映像位于单独的目录中,但是具有相同的种子,因此可以正确加载它们。标签也正确,我通过查看ImageDataGenerator生成的文件名和目录进行了检查。

该模型非常简单,我认为这不是问题所在

>4
>5
>9
>9
>9

图像生成器如下

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')

编辑:好的,算法现在正在训练中。精度似乎正在提高,但是验证精度停留在0.111(1/9,这意味着网络只是在猜测图像的标签)。但是,训练的准确性确实有所提高,因此至少现在已经过拟合了。

EDIT2 :我已经手动编辑了目录,以便不再使用子集。目录如下拆分

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

现在更有趣的一点是,验证损失增加而训练损失减少。从运行4个时期开始,这些就是结果

-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...

更新 已检查图像对和图像标签。所有图像标签均正确。所有图像都正确配对。

2 个答案:

答案 0 :(得分:0)

低训练损耗和高val损耗通常表示过拟合。

在这种情况下,第一转换层的输出可能太大而无法馈送到密集层,这会导致密集层内部的权重矩阵过大,从而过度拟合数据。

也许堆叠更多的Conv2d + MaxPooling2d层会减少密集层的输入大小,并且会导致神经网络中参数总数的减少,从而帮助您应对过拟合。

答案 1 :(得分:0)

并不是真正的答案,但我的问题有太多更新:

首先,我发现通过设置shuffle = False并不是培训。通过更改shuffle = true,实际上可以看到一些结果!

第二,该模型不够深入。添加另一个(或两个)卷积层有很大帮助。

关于为什么设置shuffle = True有帮助。我认为这是因为,如果所有数据每次都以相同的方式,通过相同的方式通过网络,则势必训练得不好,因为它不会给模型带来太多变化。通过将shuffle = True设置为两种情况下使用相同的种子,这意味着混洗量相同(因此图像仍然可以正确配对),但是它们通过网络的顺序是不同的。

如果任何人都可以添加其他信息,请这样做。