我使用Keras进行二进制分类问题。我正在使用LeNet的以下改编:
lenet_model = models.Sequential()
lenet_model.add(Convolution2D(filters=filt_size, kernel_size=(kern_size,
kern_size), padding='valid', input_shape=input_shape))
lenet_model.add(Activation('relu'))
lenet_model.add(BatchNormalization())
lenet_model.add(MaxPooling2D(pool_size=(maxpool_size, maxpool_size)))
lenet_model.add(Convolution2D(filters=64, kernel_size=(kern_size,
kern_size), padding='valid'))
lenet_model.add(Activation('relu'))
lenet_model.add(MaxPooling2D(pool_size=(maxpool_size, maxpool_size)))
lenet_model.add(Convolution2D(filters=128, kernel_size=(kern_size,
kern_size), padding='valid'))
lenet_model.add(Activation('relu'))
lenet_model.add(MaxPooling2D(pool_size=(maxpool_size, maxpool_size)))
lenet_model.add(Flatten())
lenet_model.add(Dense(1024, kernel_initializer='uniform'))
lenet_model.add(Activation('relu'))
lenet_model.add(Dense(512, kernel_initializer='uniform'))
lenet_model.add(Activation('relu'))
lenet_model.add(Dropout(0.2))
lenet_model.add(Dense(1, kernel_initializer='uniform'))
lenet_model.add(Activation('sigmoid'))
lenet_model.compile(loss='binary_crossentropy', optimizer=Adam(),
metrics=['accuracy'])
但我得到了这个:
ValueError: Error when checking model target: expected activation_6 to have shape (None, 1) but got array with shape (1652, 2). It gets resolved if I use 2 in the final Dense layer.
答案 0 :(得分:2)
我建议先检查数据的维度。训练数据集目标是2维的,但模型获得1维数据。
您已将lenet_model.add(Dense(1, kernel_initializer='uniform'))
设置为接受二维数据。您需要设置最终的密集图层形状,使其接受目标形状(None,2)
lenet_model.add(Dense(2, kernel_initializer='uniform'))
应该是对数据进行预处理,使得目标数据是一维数据。
在下次编写代码之前,请考虑阅读文档。
答案 1 :(得分:1)
似乎在预处理步骤中,您已经使用函数将数字类标签转换为分类标签,即在单热编码方案中表示数字类(在Keras中,to_categorical(y, num_classes=2)
将完成此工作为了你)。
由于您正在处理二进制问题,如果原始标签为0和1,则编码的分类标签将为01s和10s(在以单热方案编码的标签中,从右到左计数, n ,则该数字将为1,而该标签的其余部分为0)。这可以解释为什么错误回溯中的数据维度为(1652, 2)
。
但是,由于您已将模型中的输出维度设置为1,因此您的输出图层将期望数据中的所需标签仅为1位数,这与您应用上述任何预处理步骤之前的原始数据相对应。
因此,您可以通过取出标签的预处理或将输出维度更改为2来解决此问题。如果您坚持使用以一种热门方式编码的分类标签,您还应该切换sigmoid激活softmax激活的最后一层,因为sigmoid只处理二进制数值类,即0或1.对于二元分类问题,这两个选择的性能差别不大。
值得一提的是,您还应该注意编译此模型时使用的成本函数。一般而言,分类标签在分类交叉熵等成本函数中效果最佳。特别是对于需要使用分类标签和softmax激活的多类分类(超过2类)问题,分类交叉熵几乎应该是您的默认选择,因为它比其他一些常见的成本函数(如MSE)具有许多优势和原始错误计数。
分类交叉熵的许多好处之一就是它会惩罚一个非常自信的错误"比分类器"差不多正确"的情况要多得多,这是有道理的。例如,在使用分类交叉熵作为成本函数的二进制分类设置中,95%确定给定实例属于0类而实例属于1类的分类器将比51%的分类器受到更多惩罚。确定何时犯了这个错误。其他一些成本函数(如原始错误计数)对于"确定"的方式不敏感。分类器是在做出决策时,那些成本函数只考虑最终的分类结果,这实际上意味着丢失了大量有用的信息。其他一些成本函数(如MSE)会更加强调错误分类的实例,这并非总是具有所需的特征。