Skip to main content
 首页 » 编程设计

python之Keras 多输入模型损失直线下降,不训练

2025年05月04日10zhwl

在使用 keras 的多输入模型时,该模型根本不进行训练。准确率飙升到接近 100% 而损失直线下降,所以我认为数据生成有问题。

我使用的是多输入 keras 模型,具有同一对象的两个图像,只是旋转了。计划是通过它自己的 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 个 epoch,结果如下

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 

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

请您参考如下方法:

低训练损失和高 val 损失通常指向过度拟合。

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

也许堆叠更多的 Conv2d + MaxPooling2d 层将减少输入到密集层的大小,这将导致神经网络中参数总量的减少,帮助您处理过拟合。