Keras脏话识别NER模型准确率99%却全预测为同一类别问题求助
核心问题原因
- 预测代码存在低级错误
你当前的预测代码逻辑完全错误:输入的测试句子没有做分词,直接遍历字符串取单个字符做映射,输入给模型的id完全不是对应单词的编码,模型自然无法输出正确结果。 - 类别极度不平衡导致的准确率幻觉
你的数据集中脏话类token占比极低(估算不足1%),模型只要把所有token都判定为非脏话O,就能轻松达到99%以上的准确率,你观测到的低损失、高准确率完全是模型走捷径的结果,不代表模型真正学会了识别脏话。你之前做人名、机构名NER时实体占比远高于当前脏话的占比,因此不会触发该问题。 - 评估指标选择错误
类别不平衡场景下,整体准确率没有任何参考价值,你应该关注脏话类别的召回率、F1值,这两个指标才能真实反映模型的识别效果。 - 你认为「序列标注任务无法使用类别权重」是错误认知,不管是手动给损失加类别权重,还是用自适应的损失函数,都可以适配序列标注场景。
修复方案
- 首先修复预测代码的逻辑错误:
max_len = 50 test_sent = "Fucking fuck fuck you asshole bullshit fuck you bitch" # 先对测试句子分词 test_tokens = test_sent.split() word_num = len(test_tokens) # 单词转id test_input = [[word2idx.get(w, 0) for w in test_tokens]] # 做padding test_input = pad_sequences(maxlen=max_len, sequences=test_input, padding="post", value=vocab_len-1) pred = model.predict(test_input) pred = pred.argmax(axis=-1)[0][:word_num] labels = {v: k for k, v in label2idx.items()} prediction = [labels[word] for word in pred] print(prediction)
- 替换损失函数解决类别不平衡问题,推荐使用Focal Loss,自动对稀有类别加权:
import tensorflow as tf def focal_loss(gamma=2.0, alpha=0.9): # alpha设为0.9是给稀有类别脏话更高的权重,可根据实际效果调整 def loss(y_true, y_pred): epsilon = 1e-7 y_pred = tf.clip_by_value(y_pred, epsilon, 1.0 - epsilon) cross_entropy = -y_true * tf.math.log(y_pred) loss = alpha * tf.math.pow(1 - y_pred, gamma) * cross_entropy return tf.reduce_mean(tf.reduce_sum(loss, axis=-1)) return loss # 编译模型时替换损失 model.compile(optimizer = opt, loss=focal_loss(gamma=2, alpha=0.9), metrics=["accuracy"])
- 数据层面做重采样:将包含脏话的句子重复采样3~5倍,或对不包含脏话的句子做欠采样,保证训练集中带脏话的句子占比不低于10%。
- 替换评估指标:训练过程中新增脏话类别的召回率、F1值作为核心评估指标,停止用整体准确率判断模型效果。
- 可选优化:在BiLSTM层后新增CRF层,序列标注任务加入CRF可以显著提升实体识别的准确率,比单独使用softmax输出效果更好。
内容的提问来源于stack exchange,提问作者taga
相关产品推荐
相关产品推荐

