首页 > 解决方案 > 如何更正此错误:ValueError: logits and labels must have the same shape ((None, 2) vs (None, 1))

问题描述

我是 CNN 的新手,所以我猜我在这里犯了一个基本错误。我正在尝试对 UTKFace 数据集进行年龄估计和性别分类。我制作了一个如下所示的数据框:

在此处输入图像描述

我已经使用 Sklearn train_test_split 拆分了数据

train_validation, test_df = train_test_split(df, test_size=0.25)


train_df, validation_df = train_test_split(train_validation, test_size=0.3333)

我编写了以下代码来进行一些数据扩充:

from keras.preprocessing.image import ImageDataGenerator


train_datagen = ImageDataGenerator(
    rescale=1./255,
    rotation_range = 40,
    width_shift_range = 0.2,
    height_shift_range = 0.2,
    shear_range = 0.2,
    zoom_range = 0.2,
    horizontal_flip = True,
    fill_mode = 'nearest')
test_datagen = ImageDataGenerator(rescale=1./255)
 
batch_size = 32

train_generator = train_datagen.flow_from_dataframe(
    train_df,
    x_col="file",
    y_col=["age","gender"],
    batch_size=batch_size,
    class_mode='multi_output')

val_generator = test_datagen.flow_from_dataframe(
    validation_df,
    x_col="file",
    y_col=["age","gender"],
    batch_size=batch_size,
    class_mode='multi_output')

然后我从这篇文章(https://towardsdatascience.com/building-a-multi-output-convolutional-neural-network-with-keras-ed24c7bc1178)中编辑了模型,使其只有模型的年龄和性别分支:

class UtkMultiOutputModel():

    def make_default_hidden_layers(self, inputs):
        """
        Used to generate a default set of hidden layers. The structure used in this network is defined as:
        
        Conv2D -> BatchNormalization -> Pooling -> Dropout
        """

        
        x = Conv2D(16, (3, 3), padding="same")(inputs)
        x = Activation("relu")(x)
        x = BatchNormalization(axis=-1)(x)
        x = MaxPooling2D(pool_size=(3, 3))(x)
        x = Dropout(0.25)(x)
        x = Conv2D(32, (3, 3), padding="same")(x)
        x = Activation("relu")(x)
        x = BatchNormalization(axis=-1)(x)
        x = MaxPooling2D(pool_size=(2, 2))(x)
        x = Dropout(0.25)(x)
        x = Conv2D(32, (3, 3), padding="same")(x)
        x = Activation("relu")(x)
        x = BatchNormalization(axis=-1)(x)
        x = MaxPooling2D(pool_size=(2, 2))(x)
        x = Dropout(0.25)(x)
        return x
  
    def build_gender_branch(self, inputs, num_genders=2):
        """
        Used to build the gender branch of our face recognition network.
        This branch is composed of three Conv -> BN -> Pool -> Dropout blocks, 
        followed by the Dense output layer.
        """
        x = Lambda(lambda c: tf.image.rgb_to_grayscale(c))(inputs)
        x = self.make_default_hidden_layers(inputs)
        x = Flatten()(x)
        x = Dense(128)(x)
        x = Activation("relu")(x)
        x = BatchNormalization()(x)
        x = Dropout(0.5)(x)
        x = Dense(num_genders)(x)
        x = Activation("sigmoid", name="gender_output")(x)
        return x
    def build_age_branch(self, inputs):   
        """
        Used to build the age branch of our face recognition network.
        This branch is composed of three Conv -> BN -> Pool -> Dropout blocks, 
        followed by the Dense output layer.
        """
        x = self.make_default_hidden_layers(inputs)
        x = Flatten()(x)
        x = Dense(128)(x)
        x = Activation("relu")(x)
        x = BatchNormalization()(x)
        x = Dropout(0.5)(x)
        x = Dense(1)(x)
        x = Activation("linear", name="age_output")(x)
        return x
    def assemble_full_model(self, width, height):
        """
        Used to assemble our multi-output model CNN.
        """
        input_shape = (height, width, 3)
        inputs = Input(shape=input_shape)
        age_branch = self.build_age_branch(inputs)
        gender_branch = self.build_gender_branch(inputs)
        model = Model(inputs=inputs,
                     outputs = [age_branch, gender_branch],
                     name="modelA")
        return model
    
num_races=len(dataset_dict['race_alias']))
modelA = UtkMultiOutputModel().assemble_full_model(IM_WIDTH, IM_HEIGHT)
modelA.summary()

然后我训练和编译:

from keras.optimizers import Adam
init_lr = 1e-4
epochs = 100
opt = Adam(lr=init_lr, decay=init_lr / epochs)
modelA.compile(optimizer=opt, 
              loss={ 
                  'age_output': 'mean_squared_error',  
                  'gender_output': 'binary_crossentropy'},
              loss_weights={
                  'age_output': 4., 
                  'gender_output': 0.1},
              metrics={
                  'age_output': 'mean_absolute_error', 
                  'gender_output': 'accuracy'})
batch_size = 32
history = modelA.fit_generator(train_generator, 
                    steps_per_epoch=len(train_df)//batch_size,
                    epochs=20,
                    validation_data=val_generator,
                    validation_steps=len(validation_df)//batch_size) 

我收到以下错误,我很难理解。

    ValueError: logits and labels must have the same shape ((None, 2) vs (None, 1))

通过阅读此处的其他帖子,看起来这可能是由于标签的尺寸错误。我不明白当我使用 Keras flow_from_dataframe 时会出现这种情况,并且数据帧的格式与我一样。任何人都可以帮忙吗?

标签: pythontensorflowkerasconv-neural-network

解决方案


logits 可能是 one-hot 编码的。但是,您的性别列只有 1 和 0。尝试对它们进行一次热编码。


推荐阅读