Keras分类器准确率高但预测结果异常求助
解决Keras分类器准确率高但全输出0的问题
嘿,我一眼就看出你碰到了一个典型的「准确率陷阱」——模型在数据集上准确率漂亮,但实际预测全输出0,这背后大概率是类别不平衡或者模型输出层配置错误在搞鬼,咱们一步步拆解排查:
1. 先排查数据集的类别分布
这是最常见的原因:如果你的数据集里类别0的样本占比特别高(比如90%以上),模型只要无脑输出0,准确率自然会很高,但完全没学到分类能力。你赶紧统计下每个类别的样本数量,比如用这段代码:
import pandas as pd print(pd.Series(y_train).value_counts())
要是发现类别0占绝对多数,那问题根源就在这儿了。
2. 检查模型的输出层配置
你贴的代码里没写完输出层,这可是关键中的关键!因为你是0-4的5分类任务,输出层必须这么设置:
model.add(Dense(units=5, activation='softmax'))
同时,损失函数要对应匹配:
- 如果你的标签是独热编码(比如
[1,0,0,0,0]代表类别0),用loss='categorical_crossentropy' - 如果标签是整数形式(比如直接用0、1、2、3、4),用
loss='sparse_categorical_crossentropy'
要是你不小心把输出层写成了Dense(1, activation='sigmoid'),模型会当成二分类任务来训练,自然只会输出0/1,就会出现全输出0的情况。
3. 别再只看准确率了!
准确率在类别不平衡的场景下完全是个“虚假繁荣”的指标,你得用更靠谱的评估方式:
- 用混淆矩阵看模型对每个类别的分类情况
- 用精确率、召回率、F1分数评估模型的真实性能
可以用sklearn的工具快速生成报告:
from sklearn.metrics import classification_report, confusion_matrix y_pred = model.predict(X_test) y_pred_classes = y_pred.argmax(axis=1) # 把softmax输出转成类别标签 print("混淆矩阵:") print(confusion_matrix(y_test, y_pred_classes)) print("\n分类报告:") print(classification_report(y_test, y_pred_classes))
4. 其他可能的坑
- 标签编码错误:如果用了
categorical_crossentropy,必须把标签转成独热编码,比如用keras.utils.to_categorical(y_train, num_classes=5) - Dropout过度:你加了两层0.5的Dropout,如果数据集本身不大,可能会让模型难以学习到少数类的特征,可以尝试把Dropout比例降到0.3,或者暂时去掉看看效果
- 类别权重设置:如果确实是类别不平衡,在训练时加上
class_weight='balanced',让模型给少数类更高的权重:
model.fit(X_train, y_train_onehot, epochs=50, batch_size=32, validation_split=0.2, class_weight='balanced')
修正后的完整示例代码
from keras.models import Sequential from keras.layers import Dense, Dropout from keras import optimizers from keras.utils import to_categorical from sklearn.metrics import classification_report import pandas as pd # 假设你的数据已经准备好:X_train, y_train, X_test, y_test # 先检查类别分布 print("训练集类别分布:") print(pd.Series(y_train).value_counts()) # 处理标签(独热编码) y_train_onehot = to_categorical(y_train, num_classes=5) y_test_onehot = to_categorical(y_test, num_classes=5) # 构建模型 model = Sequential() model.add(Dense(units=14, activation='relu', input_shape=(14,))) model.add(Dropout(0.3)) model.add(Dense(units=14, activation='relu')) model.add(Dropout(0.3)) # 正确的多分类输出层 model.add(Dense(units=5, activation='softmax')) # 编译模型 model.compile(optimizer=optimizers.Adam(learning_rate=0.001), loss='categorical_crossentropy', metrics=['accuracy']) # 训练模型,加上类别权重 model.fit(X_train, y_train_onehot, epochs=50, batch_size=32, validation_split=0.2, class_weight='balanced') # 评估模型 y_pred = model.predict(X_test) y_pred_classes = y_pred.argmax(axis=1) print("\n分类报告:") print(classification_report(y_test, y_pred_classes))
内容的提问来源于stack exchange,提问作者rere
相关产品推荐
相关产品推荐

