标准回答
512 限制的根因
BERT 的最大序列长度是 512 token,原因有二:一是它的位置编码是可学习的查表向量,预训练时只见过 0–511 这些位置,超出就没有对应表示;二是自注意力的计算和显存开销是序列长度的 O(L²) 平方关系,强行放大长度代价极高。
方案一:截断
最简单的做法是截断到 512。可只取头部、只取尾部,或头尾拼接(很多任务关键信息集中在首尾)。优点是零改造、推理快;缺点是中间内容直接丢失,长文档信息损失大。
方案二:滑动窗口分段 + 聚合
把长文本按窗口(可设重叠)切成若干段,每段独立过 BERT,再把各段表示聚合:分类任务可对各段 [CLS] 做最大/平均池化或加权,或按段投票;检索任务可逐段打分取最高。能覆盖全文,但段间缺乏直接交互。
方案三:层次编码
先用 BERT 编码每个段落得到段级表示,再在段级表示之上接一层 Transformer 或 RNN 做段间聚合,形成“词→段→篇”的层次结构,比简单池化更能建模跨段依赖。
方案四:长上下文模型
直接换用为长文本设计的模型:Longformer、BigBird 用稀疏注意力(局部窗口 + 少量全局 token)把复杂度降到近似线性,可处理 4K 乃至更长;也可改用支持长上下文的大语言模型。
方案五:关键句抽取后再编码
先用规则或轻量模型抽取与任务最相关的句子/段落,压缩到 512 以内再喂给 BERT,相当于先做信息浓缩。
如何选择
按任务取舍:信息集中在首尾用截断即可;需要全文覆盖且段间依赖弱用滑动窗口聚合;跨段语义强用层次编码;长度远超 512 且预算允许则直接上 Longformer/BigBird 或长上下文 LLM。
常见误区
⚠️ 常见踩坑
以为把 max_position_embeddings 改大就能直接处理长文本(位置编码未预训练过、注意力 O(L²) 开销也撑不住);忽视截断会丢中间信息;在段间依赖很强的任务里盲目用简单池化聚合而损失跨段语义。
追问
追问 1:Longformer 是怎么把注意力复杂度降下来的?
Longformer 用稀疏注意力替代全连接注意力:每个 token 只关注一个固定大小的局部滑动窗口(捕捉局部依赖),再为少数特殊 token(如 [CLS] 或任务相关位置)保留全局注意力以汇聚全文信息。这样复杂度从 O(L²) 降到约 O(L×w),近似线性,从而支持数千 token 的长文本。
追问 2:滑动窗口分段时为什么要设置重叠?
重叠是为了避免把一个完整语义单元(句子、实体、论述)切在两段边界处导致上下文被割裂。让相邻段共享一部分 token,边界附近的词在至少一段里能拥有较完整的上下文,从而减少切分带来的信息损失,提升聚合后的稳定性。
追问 3:截断时取头尾拼接相比只取头部有什么考量?
很多文档的结论或关键信息出现在结尾(如论文摘要的结论、评论的总结句),只取头部会漏掉。头尾拼接同时保留开头的背景和结尾的结论,对首尾信息双重要紧的任务更稳;但中间仍然丢失,且需根据任务经验决定头尾各取多少比例。
🔗 相似问题
同一考点的不同问法,面试官可能换着问,一起刷更稳
没找到想看的面试题?把你想看的告诉我们 →
延伸学习
按主题分类的相关资源,便于系统复习