如何在BERT建模前对拆分后的文本数据集添加SMOTE处理?
文本不平衡场景下SMOTE+BERT的操作指南
关于SMOTE的执行时机
绝对不能在tokenization之后对input_ids执行SMOTE。
input_ids是token对应词表的离散整数索引,SMOTE的核心逻辑是对连续特征做线性插值生成新样本,直接对离散的索引向量插值得到的结果既不在词表范围内,也没有任何语义逻辑,属于无效噪声样本,只会降低模型的最终效果。
正确的操作流程
首先明确通用铁则:所有过采样/欠采样操作只能作用于训练集,绝对不能触碰验证集和测试集,避免数据泄露导致评估指标失真。
针对文本场景适配SMOTE有两种可落地的方案:
方案1:语义嵌入后执行SMOTE(推荐度高)
- 用你现有的
tokenize函数先对训练、验证、测试集的原始文本做token化,得到对应input_ids和attention_mask - 加载预训练BERT模型,冻结全部参数,仅输出每个样本的<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>token嵌入作为连续语义特征
- 仅拿训练集的<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>嵌入和对应标签执行SMOTE过采样,生成少数类的新样本
- 把原始+生成的训练集特征喂给下游分类层训练,验证、测试集直接用原始嵌入做评估即可
方案2:生成式过采样替换原生SMOTE(效果更优)
如果不想处理嵌入层逻辑,可以用轻量文本生成模型(比如T5-small、GPT2-mini)针对训练集的少数类文本生成语义相近的新样本,把生成的样本合并到原始训练集之后,再统一做token化送入BERT训练即可。
你可以基于现有代码做如下调整:
# 假设你已经生成少数类新文本存入列表new_minority_tweets x_train_aug = pd.concat([x_train, pd.DataFrame({"tidy_tweet": new_minority_tweets})], ignore_index=True) # 仅对增强后的训练集做token化 train_input_ids, train_attention_masks = tokenize(x_train_aug) # 验证、测试集保持原逻辑不变,不做任何增强 valid_input_ids, valid_attention_masks = tokenize(x_valid) test_input_ids, test_attention_masks = tokenize(x_test)
补充提示
如果你的数据集不平衡比例低于1:10,可以直接给BERT的损失函数加类别权重解决不平衡问题,不需要引入SMOTE,实现成本更低。
内容的提问来源于stack exchange,提问作者hellomoto
相关产品推荐
相关产品推荐

