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