You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NLP敏感信息检测任务中类别失衡问题的解决方案咨询

敏感信息检测模型的类别失衡问题及解决方案

问题背景

我正在训练NLP模型检测医疗笔记中的敏感信息,需识别15类敏感内容。为让模型区分敏感与非敏感数据,新增了非敏感类别,但数据集出现严重失衡——模型对非敏感数据预测准确率极高,却无法有效识别其余15类敏感类别。

纠结点:

  • 屏蔽非敏感数据,怕模型无法区分敏感/非敏感内容
  • 考虑对海量非敏感数据做大量欠采样,但不确定是否合理

当前数据集与模型细节:

  • 数据集:含伪造敏感信息的医疗笔记,Excel格式(26MB),按50%训练集、25%验证集、25%测试集划分,确保测试集有足够敏感类样本
  • 数据处理:以句子为单位分类,处理为长度38的token序列,用bert-base-uncased分词器;每个token带标签(padding为0,非敏感为1,敏感类为2-15),训练时通过mask忽略padding
  • 模型:因数据集规模小,采用GRU模型,已加Dropout缓解过拟合,但仅非敏感类指标优异,其余类别表现差

针对性解决方案

1. 类别权重调整(优先尝试)

在损失函数中为少数类(敏感类)赋予更高权重,强制模型关注这些类别的错误。修改模型编译部分:

import numpy as np
from sklearn.utils.class_weight import compute_class_weight

# 过滤padding标签(标签0),仅计算有效类别权重
train_labels = train_y_gru.flatten()
train_labels = train_labels[train_labels != 0]
class_weights = compute_class_weight('balanced', classes=np.unique(train_labels), y=train_labels)
class_weight_dict = {i+1: class_weights[i] for i in range(len(class_weights))}
class_weight_dict[0] = 0  # padding标签权重设为0,不参与损失计算

# 编译模型时传入类别权重
model_gru.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
                  metrics=['sparse_categorical_accuracy'], class_weight=class_weight_dict)

2. 分层欠采样(谨慎操作)

不建议直接大量砍掉非敏感数据,采用分层欠采样更合理:

  • 仅对训练集操作,验证集、测试集保留原始分布,避免评估失真
  • 按敏感类样本量的2-5倍保留非敏感样本,既缩小失衡比例,又保留足够非敏感数据让模型学习区分边界

3. 敏感类数据增强

针对敏感类样本做数据增强,提升样本量:

  • 同义词替换:用医疗领域同义词库替换敏感词(比如用"心肌梗死"替换"心梗")
  • 句子重组:在不改变敏感信息类别的前提下,调整句子语序
  • 回译:将敏感句子翻译成英文再译回中文,生成语义相近的变体样本

4. 评估与输出调整

  • 放弃准确率作为核心评估指标,改用F1-score、精确率/召回率,更能反映少数类的真实表现
  • 降低非敏感类的预测阈值:比如将原本0.5的阈值提升至0.7,让模型更倾向于预测敏感类

5. 模型结构小优化

在现有GRU基础上添加全局平均池化层,减少序列冗余信息:

from keras.layers import GlobalAveragePooling1D

model_gru = Sequential()
model_gru.add(Embedding(input_dim=vocab_size, output_dim=out_dim, input_length=input_len, mask_zero=True))
model_gru.add(GRU(64, return_sequences=True, activation='tanh'))
model_gru.add(Dropout(.25))
model_gru.add(GRU(32, return_sequences=True, activation='tanh'))
model_gru.add(Dropout(.25))
model_gru.add(GlobalAveragePooling1D())  # 添加全局平均池化
model_gru.add(Dense(numb_classes, activation='softmax'))

原始模型代码

#Dataset statistics
numb_classes = 17 #Number of classes in the NLP problem
vocab_size = 30522 #The vocab size of the bert-base-uncased model
out_dim = 100
input_len = 38

callback = keras.callbacks.EarlyStopping(monitor='loss', patience=3)

model_gru = Sequential()
model_gru.add(Embedding(input_dim=vocab_size, output_dim=out_dim, input_length=input_len, mask_zero=True))
model_gru.add(GRU(64, return_sequences=True, activation='tanh'))
model_gru.add(Dropout(.25))
model_gru.add(GRU(32, return_sequences=True, activation='tanh'))
model_gru.add(Dropout(.25))
model_gru.add(Dense(numb_classes, activation='softmax'))

model_gru.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['sparse_categorical_accuracy'])
history_gru = model_gru.fit(train_X_gru, train_y_gru, epochs=10, batch_size=70,
                        validation_data=(val_X_gru, val_y_gru))

内容的提问来源于stack exchange,提问作者dunha2j

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:47:33