🏠 总目录📚 本教程 06 · 文本分类
📑 本页目录(点开跳转)

文本分类

35 分钟 | ⭐ NLP 赛最常见的题型


🎯 一句话

文本分类看起来简单,但竞赛里拉开差距的从来不是「用哪个模型」,而是几个具体决策:长文本怎么截断、不均衡怎么处理、池化怎么选、以及输入怎么组织。这一章就是这些决策的清单。


一、文本分类任务建模

1.1 任务类型

类型 说明 典型赛题
二分类 正/负情感、有害/无害 有害评论检测
多分类 多个互斥类别 新闻分类、意图识别
多标签 一个样本可属多个类别 推文多标签分类
层次分类 类别存在层级关系 商品分类

1.2 分类头设计

方法 说明 适用场景
CLS + Linear 取[CLS]向量接全连接层 最简单,通用基线
CLS + MLP 取[CLS]向量接多层感知机 需要更强表达能力
多路池化拼接 CLS + MaxPool + AvgPool + Self-Attention拼接 追求极致性能
胶囊网络 用动态路由提取胶囊特征 序列空间特征丰富

1.3 多标签分类

维度 说明
损失函数 BCEWithLogitsLoss,每个标签独立计算二元交叉熵
阈值优化 默认0.5不一定最优,需在验证集上搜索最优阈值
标签相关性 可用Classifier Chain或Label Powerset建模标签间依赖

二、样本不均衡处理(NLP专项)

2.1 文本分类中的不均衡

维度 说明
常见场景 推文分类中,部分标签出现频率极低
分层K折 使用StratifiedKFold确保每折中各类别比例一致
类别权重 在CrossEntropyLoss中设置weight参数,小类权重更高
Focal Loss 自动关注难分样本,对小类样本给予更多关注

2.2 验证集构造(NLP专项)

维度 说明
分层划分 按标签比例划分,确保验证集类别分布与训练集一致
多标签场景 使用IterativeStratification处理多标签分层划分
固定种子 固定随机种子确保实验可复现

三、模型选择实践

3.1 模型对比基准

模型 推文分类F1 训练时间 显存占用
BERT Base 基线 1x 1x
RoBERTa Base +1~2% 1x 1x
DeBERTa Base +2~3% 1.2x 1.2x
DeBERTa Large +3~5% 3x 3x
DeBERTa XLarge +4~6% 8x 8x

3.2 模型选型天花板

维度 说明
核心结论 直接选用在结构上更具优势的DeBERTa V2/V3模型替代原生BERT
注意力解耦 DeBERTa的Disentangled Attention特性在文本语境捕捉上更优
延迟位置编码 绝对位置编码延迟添加,对位置敏感任务更有效
实践建议 先用Base快速验证,确认有效后切换Large/XLarge

四、QA输入顺序调换

维度 说明
问题背景 BERT等预训练模型对输入顺序敏感,Question-Answer和Answer-Question的表征不同
核心方法 将原始QA对调换顺序(Q-A → A-Q),构造第二份训练数据
融合策略 将原始顺序和调换顺序的预测概率取平均
核心优势 等价于免费的数据增强,不增加模型参数
适用场景 问答匹配、文本相似度等成对文本任务

五、USE冻结式迁移学习

维度 说明
核心方法 使用Universal Sentence Encoder(USE)提取句子向量,冻结不训练,直接接分类器
实现方式 hub.load("https://tfhub.dev/google/universal-sentence-encoder/4")
优势 无需GPU即可训练,推理速度快,适合快速出结果
对比 在小数据集上,USE冻结式迁移往往性价比最高
局限 性能天花板低于BERT微调

六、社交媒体特征融合

维度 说明
文本统计特征 text_len、word_count、avg_word_len
社交媒体特征 hashtag_count、mention_count、url_count
语义辅助特征 digit_count、uppercase_ratio
缺失值二值化 has_keyword、has_location
融合方式 与BERT/DeBERTa的CLS向量拼接后送入分类器
标准化 使用StandardScaler对非文本特征标准化

七、混合池化策略(文本分类专项)

7.1 多路池化拼接

维度 说明
实现方式 同时声明BERT-Pooler、Max Pooling、Average Pooling、Self-Attention Pooling以及Dynamic Routing等多种池化操作
融合策略 将这些结果进行汇总和加总后再送入分类器
核心优势 多维度提取特征能让分类结果更加稳定全面

7.2 弃用Flatten()改用降维Pooling

维度 说明
问题背景 官方Baseline在提取序列特征后直接使用Flatten()操作,导致分类器参数量暴增
导致后果 庞大的分类器极易在小数据或不平衡数据上严重过拟合
解决方案 通过各类Pooling将变长的序列维度压缩为1维
最终效果 模型更容易被有效训练

八、脱敏ID还原与词频映射

维度 说明
问题背景 部分竞赛(如医疗NER)将原始文本脱敏为数字ID,如"患者 123 456 789"
词频映射原理 统计脱敏ID在训练集+测试集中的出现频率,与开源BERT词表中各Token的出现频率进行排序匹配
映射逻辑 出现频率第1高的脱敏ID → 映射为BERT词表中频率第1高的Token
映射成功率 高频词(标点、停用词)映射成功率高;低频词(专有名词)映射成功率低
失败处理 映射失败的ID使用Word2Vec向量进行兜底初始化
核心优势 让脱敏语料也能利用开源预训练模型的强大初始权重

九、长文本截断策略

策略 说明 适用场景
Head截断 保留前512个Token 文本开头信息最关键
Tail截断 保留后512个Token 文本结尾信息最关键
Head+Tail截断 前128 + 后384个Token 兼顾首尾信息
滑动窗口 多次截取,结果融合 长文本信息均匀分布
动态截断 按实体位置截取 NER任务

十、分类任务实战流程

1. EDA → 分析类别分布、文本长度、数据质量
2. 基线模型 → BERT Base + CLS + Linear
3. 模型升级 → RoBERTa / DeBERTa
4. 池化优化 → 多路池化拼接替代单一CLS
5. 训练优化 → 对抗训练 + SWA + Multi-Dropout
6. 数据优化 → 数据增强 + 伪标签
7. 融合冲刺 → 多模型 + 多折 + 多种子融合
8. 后处理 → 阈值优化 + 规则修正

十一、对比学习在分类中的应用

维度 说明
核心思想 拉近相似样本的表征,推远不相似样本的表征
SimCSE 同一句子两次Dropout过模型,作为正样本对,其他句子作为负样本
ConSERT 多种数据增强(shuffle/ cutoff/ dropout)构造正样本对
训练方式 先对比学习预训练表征,再在分类任务上微调
适用场景 标注数据少、无标注数据多时,改善表征质量
竞赛经验 医疗/法律等特定领域,对比学习预训练可提升0.5~1个百分点

十二、课程学习(Curriculum Learning)

维度 说明
核心思想 按照从易到难的顺序训练模型,先学简单样本再学困难样本
难度衡量 用预训练模型的预测置信度、句子长度、标注一致性等衡量
实现方式 按置信度排序,先训练高置信度(简单)样本,逐步加入低置信度样本
效果 训练更稳定,收敛更快,最终精度略有提升
与伪标签关系 课程学习可辅助伪标签筛选,先学高置信度伪标签样本

十三、少样本/零样本分类

方法 说明 适用场景
Prompt-based分类 将分类任务转化为填空任务,利用预训练模型的MLM能力 每类仅几个样本
PET (Pattern-Exploiting Training) 设计Prompt模板 + MLM预测,少样本下超越标准微调 极少标注数据
LM-BFF 自动搜索Prompt模板 + 少样本微调 自动化Prompt设计
零样本分类 用NLI模型做零样本推理:前提="这是一篇关于{label}的文章" 无标注数据
外部数据迁移 在大规模外部数据集预训练后迁移到目标任务 数据量不足

Prompt分类示例

模板: "这篇评论的情感是[MASK]。"
标签映射: [MASK]="积极" → 正面, [MASK]="消极" → 负面
优势: 将分类问题转化为预训练模型擅长的MLM任务

十四、多任务学习在分类中的应用

维度 说明
核心思想 同时训练多个相关任务,共享底层表征,互相正则化
共享方式 共享编码器(BERT),各自独立的分类头
Loss权重 不同任务Loss权重需平衡,通常按任务重要性或梯度大小调整
竞赛应用 多标签分类中,同时训练主标签和辅助标签
与多标签区别 多任务是显式不同任务,多标签是同一任务多输出

十五、文本分类常见踩坑点

坑点 原因 解决方案
验证集分数虚高 验证集与训练集分布不一致 对抗验证 + 分层K折
模型训飞Loss为0 学习率过大或未设Warmup lr降至1e-5 + Warmup 0.1
多标签阈值不对 默认0.5非最优 验证集搜索每标签最优阈值
长文本信息丢失 暴力截断512丢失关键信息 Head+Tail截断 / 滑动窗口
类别极度不均衡 小类样本不足1% Focal Loss + 采样策略 + 数据增强
伪标签引入噪声 低置信度样本标签错误 置信度阈值0.9+ + 多模型投票生成

🔗 这一章连到哪里

去哪为什么
Kaggle 05 预训练模型详解[CLS] 到底是什么——BERT 架构里它被训成「句子级表征,用于分类任务」,这正是本章第七节拿它当默认池化、又要拿别的池化去比的前提
大模型导论 02 Transformer 原理注意力和一层 Transformer 里到底在算什么(⚠️ 那一章是 decoder-only 视角,[CLS] 和池化不在里面,那两件事看上一行和本章第七节)
大模型导论 03 Tokenizer 与上下文长文本截断、max_len、脱敏 ID 还原都绕不开分词器
ML基础 05 评估与过拟合类别不均衡下 accuracy / F1 / AUC 各自失效在哪

✅ 检查点

  1. 长文本超过模型最大长度时,有哪几种处理策略?各自的代价是什么?
  2. 为什么「池化方式」值得单独调?常见的选择有哪些?
  3. QA 类任务里调换输入顺序为什么会影响分数?
  4. NLP 场景的样本不均衡,和表格场景的处理有什么不同?
  5. 文本分类最常见的踩坑点是什么?
👀 答案
  1. 头部截断(最简单,适合关键信息在开头的文本)②头尾拼接(如取前 128 + 后 382,很多赛题最优)③滑窗切块 + 结果聚合(信息不丢,但推理成本 ×N 且要设计聚合方式)④先用一个模型抽取关键段落再送入(复杂但对超长文档有效)。代价依次是:信息损失 → 信息损失 → 计算成本 → 系统复杂度。
  2. 因为不同池化提取的是不同层次的信息[CLS] 是模型专门训练的句子表示;mean pooling 更稳、对长文本更好;max pooling 突出最强信号;混合池化(多种拼接)几乎总是不差。而且它零成本可调——改一行代码,跑一次 CV。
  3. 因为注意力的位置偏好不是均匀的——靠前和靠后的内容更容易被充分利用(中间迷失现象)。把问题放前面还是把上下文放前面,会改变模型「先看到什么」,在某些赛题上能带来可观的分差。这是零成本的实验,值得试。
  4. NLP 里过采样少数类的副作用更大——重复的文本会让模型死记那几条样本。所以更常用:调整类别权重、Focal Loss、以及文本增强(回译/同义词替换)来造真正不同的少数类样本,而不是简单复制。
  5. 训练和推理的预处理不一致——比如训练时做了小写化/去标点/截断策略 A,推理时忘了或用了策略 B。症状是 CV 很好但 LB 明显偏低。把预处理封装成一个函数,两边都只调它。

🛑 可以停在这里

走神救援
文本分类拉开差距的不是模型,是几个具体决策。长文本截断四策略:头部截断 → 头尾拼接(如前128+后382,很多赛题最优) → 滑窗切块+聚合(推理×N)→ 先抽关键段落;代价依次是信息损失→信息损失→计算→复杂度。⭐池化方式零成本可调,值得单独试:[CLS] 是专门训的句表示,mean 更稳(长文本友好),max 突出最强信号,混合池化几乎总是不差QA 类调换输入顺序会影响分数——因为注意力的位置偏好不均匀(中间迷失),零成本实验值得试。⚠️NLP 的不均衡别简单过采样(重复文本会让模型死记),优先用类别权重/Focal Loss/回译等增强造真正不同的样本。⭐最常见的坑:训练和推理的预处理不一致(CV 好但 LB 偏低)——把预处理封装成一个函数,两边都只调它。

打卡记录保存在你的浏览器里,首页能看到总进度