Keras二分类任务中正类F1分数为0,使用flatten()仍未解决
问题分析与解决方案
核心错误:层顺序完全颠倒
你的代码里先添加Dense层再做Flatten是致命问题。DenseNet121输出的是三维特征图(形状类似(batch_size, 7, 7, 1024)),直接在特征图后接Dense层,会对每个空间位置的通道维度单独做全连接,而非把整个特征图展平成一维全局特征向量后再做全连接。这种错误的层结构会导致模型无法学习到正类的有效特征,最终出现正类F1为0的情况。
修正后的正确层顺序:
base_model = Sequential() base_model.add(dense_net) base_model.add(Flatten()) # 先将特征图展平为一维特征向量 base_model.add(Dense(units=8, activation='relu')) base_model.add(Dropout(0.5)) base_model.add(Dense(1, activation='sigmoid', name='output'))
其他优化建议
- 解冻部分预训练层:你冻结了DenseNet的所有层,仅训练顶层小网络,可能无法提取足够适配任务的特征。可以尝试解冻最后几个卷积块(比如最后3个block),配合小学习率微调:
# 先冻结所有层 for layer in dense_net.layers: layer.trainable = False # 解冻DenseNet121最后3个卷积块(约最后24层) for layer in dense_net.layers[-24:]: layer.trainable = True # 微调时使用小学习率 model1.compile(optimizer=Adam(learning_rate=1e-5), loss='binary_crossentropy', metrics=['accuracy'])
- 监控正类专属指标:训练时加入精确率、召回率指标,实时跟踪正类表现,避免仅依赖准确率:
from keras.metrics import Precision, Recall model1.compile( optimizer=Adam(learning_rate=1e-4), loss='binary_crossentropy', metrics=['accuracy', Precision(name='precision'), Recall(name='recall')] )
调整分类阈值:默认用0.5作为sigmoid输出的分类阈值,若模型输出整体偏低,可根据验证集的PR曲线找到更适合的阈值,而非固定使用0.5。
加入数据增强:即使数据集均衡,随机翻转、裁剪、亮度调整等图像增强操作能提升模型泛化能力,避免过拟合。
内容的提问来源于stack exchange,提问作者thihansa mudalige
相关产品推荐
相关产品推荐

