在使用 BERT 处理 长文本预测任务(如新闻分类、法律文书预测、长段情感分析等)时,需要特别注意 BERT 的输入长度限制和模型架构的特点。以下是构造训练样本的系统性方法,适用于各类长文本任务。
一、BERT 输入限制
BERT 的最大输入长度是:
-
BERT-base
/BERT-large
默认最多 512 个 tokens -
包括
[CLS]
和[SEP]
标记在内
超过 512 tokens 的输入文本必须截断或分段处理,否则会报错。
二、训练样本构造策略
1. 只保留前 512 tokens(最简单)
适用场景:关键信息集中在开头的任务
tokens = tokenizer.encode(text, max_length=512, truncation=True, padding='max_length')
缺点:
-
丢失大量后文信息,尤其在新闻、法律类长文本中可能导致性能下降
2. 滑动窗口(Sliding Window)
适用场景:全篇重要,需覆盖全文
将文本切成多个段落,使用固定窗口滑动,生成多个训练样本,每个不超过 512 tokens:
-
假设窗口大小为 512,滑动步长为 256(可调)
-
将每个窗口视为一个训练样本,标签相同
代码示意:
def split_long_text(text, tokenizer, max_len=512, stride=256):
tokens = tokenizer.encode(text, add_special_tokens=True)
samples = []
for i in range(0, len(tokens), stride):
chunk = tokens[i:i+max_len]
if len(chunk) < max_len:
chunk += [tokenizer.pad_token_id] * (max_len - len(chunk))
samples.append(chunk)
return samples
训练时,将这些 chunk 作为样本输入,标签相同。
3. 取首尾拼接策略(Head+Tail)
适用场景:前后信息都重要,中间可舍弃
取前 N tokens + 后 M tokens,使总长不超过 512。例如:
N = 256
M = 254 # 再加上 [CLS] 和 [SEP]
tokens = tokenizer.encode_plus(
text[:N] + text[-M:],
max_length=512, truncation=True, padding='max_length'
)
优点:简洁,适用于“首因/近因”模型(如法律文本判决)
4. 层次结构(Hierarchical BERT)
适用场景:长文结构明确,句级信息重要
将文本按句子切分,得到多个句子向量
每个句子用 BERT 编码成向量(取 [CLS]
)
用另一个 RNN/CNN/Transformer 聚合这些句向量进行分类
文本 → 分句 → 每句进 BERT → 得到句向量序列 → 聚合(分类器)
这种结构可以处理 10,000+ tokens 的文本,常用于:
-
长文情感分析(IMDb)
-
法律文书判别(如 CAIL)
-
学术论文分类
三、标签构造方式(根据任务)
任务类型 | 标签设计 |
---|---|
文本分类 | 每个样本一个标签 |
文本回归 | 每个样本一个数值目标 |
文本排序 | 构造 pairwise 训练样本 |
多段落多标签 | 每段一个样本,共享或不同标签(Multi-label) |
四、注意:训练阶段与预测阶段一致
-
如果训练时使用了滑动窗口,预测时也需按相同窗口预测、然后聚合(如求最大、平均)
-
如果用了首尾拼接,预测时也必须用同样策略
五、补充技巧
技巧 | 说明 |
---|---|
句子打分选择段落 | 用 TextRank / TF-IDF 先选重要句子再进 BERT |
多段合并投票 | 每段独立预测后做 多数投票 得最终结果 |
使用 Longformer | 处理长文本更自然(4K tokens+),可替代 BERT |
总结表:不同场景选用策略
场景 | 推荐策略 |
---|---|
关键信息在前 | 直接截断前 512 |
信息分布均匀 | 滑动窗口 |
前后重要,中间可舍 | 首尾拼接 |
结构清晰、长文 | 层次式 BERT |
高效高性能需求 | Longformer、BigBird、RoBERTa 等 |