复试项目二
学习了self-attention,并使用Bert完成影评情感分类任务
对比RNN和LSTM的优势和劣势,sa的架构
RNN 是一类会保留历史信息的循环神经网络,通过隐藏状态传递,把前面的信息带给后面,用来处理序列数据。 LSTM 是改进版的 RNN,通过门控机制(遗忘门、输入门、输出门,再加上细胞状态(记忆单元))控制信息的遗忘和记忆,解决了普通 RNN 长期依赖、梯度消失的问题。 自注意力机制直接建模全局依赖,不像 RNN、LSTM 那样只能按顺序一步步计算,并行计算效率更高,还能避免长序列梯度消失,捕捉远距离依赖更稳定、效果更强。
RNN往神经网络里面放了一个传家宝,这个传家宝里面记忆着历史信息,每层网络都会往传家宝里放自己的东西。但缺点是如果上下文距离过长,传家宝里会放入很多没用的东西。于是引出LSTM,使用遗忘门输入门输出门和记忆单元解决。但需要一句一句传入,效率太低,故引入自注意力机制,可以同时获取全局信息,并行处理效率更高。
Bert的原理?
- 结构:由 多层 Transformer Encoder 堆叠而成(base 12 层);
- 核心:双向多头自注意力,能同时看到一个词左边 + 右边的全部上下文;
- 模式:预训练 + 微调 两阶段范式。
BERT 是一个只使用 Transformer 编码器(Encoder)、采用双向自注意力机制的预训练语言模型。
Bert结构?
表格
| 你的叫法 | BERT 标准命名 | 核心作用 |
|---|---|---|
| 词编码层 | 输入嵌入层(Input Embedding) | 把文字转成计算机能懂的向量 |
| bertlayer 层 | 编码器堆叠层(Encoder Stack) | 理解上下文语义(BERT 核心) |
| poolout 层 | 输出层(Output Layer) | 输出句子 / 词级的语义表征 |
二、逐层通俗解释(附核心逻辑)
1. 词编码层(输入嵌入层):给文字发 “带信息的身份证”
这是 BERT 的第一层,核心是把离散的文字(字 / 词)转换成连续的向量,而且不是简单的词向量,还叠加了 3 类关键信息:
- Token Embedding:基础词向量(比如 “苹果” 对应一个向量,区分不同字 / 词);
- Segment Embedding:区分句子(比如问答任务中,标记哪些词属于问题、哪些属于答案);
- Position Embedding:标记位置(因为 Transformer 本身没有 “顺序感”,需要告诉模型每个词在句子里的位置)。
通俗比喻:就像给每个字 / 词办身份证,身份证上不仅写了 “我是谁”(Token),还写了 “我属于哪个句子”(Segment)、“我在句子里的第几号位”(Position)。
2. bertlayer 层(编码器堆叠层):让每个词 “读懂上下文”
这是 BERT 的核心,由 N 个(Base 版 12 层、Large 版 24 层)Transformer Encoder Layer 堆叠而成(你说的 “bertlayer” 其实就是单个 Encoder Layer)。每个 Encoder Layer 里又包含两个核心组件:
- 多头自注意力机制:让每个词 “看到” 句子里所有其他词的信息(比如 “苹果” 能看到前后的 “吃”“手机”,判断是水果还是公司);
- 前馈神经网络:对注意力机制的结果做进一步加工,提取更复杂的语义特征。
通俗比喻:就像人读句子时,不会孤立看 “苹果” 这个词,而是结合 “我吃苹果” 或 “我用苹果手机” 的上下文理解意思 —— 这一层就是让模型具备这种 “上下文理解能力”。
3. poolout 层(输出层):输出有用的语义结果
这一层的核心是把编码器层处理后的向量,转换成任务需要的形式,主要有两种输出方式(对应 “poolout” 的 “池化” 含义):
- 句子级输出:取第一个特殊标记
[CLS]的向量作为整个句子的语义表征(相当于对整句向量做 “池化”),常用于分类任务(比如情感分析、文本分类); - 词级输出:保留每个词的上下文向量,常用于命名实体识别、分词、机器翻译等需要逐词处理的任务。
通俗比喻:读完句子后,要么总结出 “这句话整体表达的是开心还是难过”(句子级输出),要么明确 “每个词在这句话里具体指什么”(词级输出)。
一、为什么 BERT 是 双向 的?
一句话核心:
因为 BERT 只使用了 Transformer 的 Encoder,且没有使用 “因果掩码”,每个词都能同时看到左边和右边所有词。
展开 2 句(背这个):
像 GPT 这种生成模型用的是 Decoder,会加 因果掩码(masked attention),
每个词只能看左边,不能看右边,所以是单向的。
BERT 用的是 Encoder,没有掩码限制,
每个单词的自注意力能同时关注整个句子的所有上下文(左 + 右),
所以叫 真正的双向语言模型。
👉 为什么要双向?
因为理解语义必须看完整上下文。
比如:
“这个苹果真好吃”
“这个苹果性能很强”
只看左边不知道 “苹果” 是什么,必须看右边才能理解。
如何训练的?
**1)**在上游使用两种方式预训练 Pre-training(最核心)
在海量无标注文本上训练,学通用语言特征,用两个任务:
① MLM 掩码语言模型(Masked Language Model)
随机把句子中80% 的词遮住([MASK],10% 的词替换,10% 的词不变;
让模型预测被遮住的词;
目的:强制模型学习双向上下文。
② NSP 下一句预测(Next Sentence Prediction)
给模型两句话 A、B;
让模型预测:B 是不是 A 的下一句;
目的:学习句子间关系、篇章逻辑。
2)微调 Fine-tuning
在你的具体任务(如酒店评论情感分类)上:
只需要在 BERT 后加一层全连接层;
用小学习率微调,快速适配任务。
Bert为什么有效?
- 真正的双向语义建模之前的模型(Word2Vec、GPT)都是单向或 “伪双向”,BERT 靠 Transformer Encoder 实现真正双向,语义理解更强。
- 自注意力****机制能建模长距离依赖能捕捉句子中很远的词之间的关系,比如评论文本里 “虽然…… 但是……” 这种逻辑。
- 大规模预训练学到通用语言知识在海量无标注文本上学语法、语义、常识,再通过微调迁移到你的酒店评论分类等下游任务。
使用了什么优化器,训练了多少轮?
(1)为什么用 AdamW,而不用普通 Adam?
- AdamW 是 带解耦权重衰减的 Adam,能更有效地做 L2 正则化,抑制模型过拟合;
- 特别适合 BERT 这类预训练模型微调,可以防止权重过大,让微调更稳定;
- 比原始 Adam 更不容易在小数据集上过拟合,更适合我这个只有几百条的酒店评论数据。
(2)为什么只训 5 轮?
- 我的数据集很小,BERT 本身已经具备很强的语义特征,微调不需要大量轮次;
- 轮数过多会导致模型严重过拟合:训练集精度很高,验证集精度下降;
- 实际实验中,3~5 轮验证集精度就达到最高并开始平稳,继续训练没有提升,还浪费显存和时间。
Bert输出是如何处理的?最后有几种处理方式?准确率多少?
BERT 会输出两部分:
- 句子里每个词的特征向量
- 句首特殊符号
**token**对应的整个句子的特征向量
在我的酒店评论情感分类项目里:我直接取 **token** 对应的整句特征,后面接一层全连接层,映射成 2 分类结果,就完成了分类。
\1. 直接用 CLS 的 pooler 输出
做法:取 pooler_output
用途:文本分类、句子匹配、情感分类(你项目用的就是这个)
特点:最简单、最常用,把 CLS 当作整句语义。
\2. 平均池化(Mean Pooling)
做法:对 sequence_output 里所有 token 的向量取平均
用途:句子表征、相似度计算
特点:比单纯 CLS 更稳定,信息更全。
\3. 最大池化(Max Pooling)
做法:对所有 token 向量按维度取最大值
用途:提取句子里最显著、最关键的特征
特点:突出关键词(如 “好”“差”),适合情感分类。
出现的问题
- 修正梯度操作:将梯度清零(
optimizer.zero_grad())调整至每个 batch 开始前,梯度裁剪(clip_grad_norm_)放在反向传播后、优化器更新前,解决梯度累积异常导致的模型偏置;
给梯度的 “总大小” 定个规矩,超过这个规矩就按比例缩小,让梯度始终在可控范围内。
- 加权采样平衡类别:通过
WeightedRandomSampler按类别样本占比设置采样权重,确保每个训练批次正负样本比例接近 1:1,避免批次分布不均引发的训练波动;
令每一批的正负样本数据数量差不多, 核心逻辑是给不同类别的样本分配不同的采样权重,让样本少的类别被抽到的概率更高,样本多的类别被抽到的概率更低
- 增强正则化:将模型 Dropout 概率从 0.1 提升至 0.3,抑制过拟合,同时加入早停策略,基于验证集 F1-score 停止训练,进一步稳定收敛效果。
由于Bert模型已经在上游完成了预训练,所以使用dropout随机隐藏一些神经元,并且加入早停机制( 早停就是在验证集损失达到最优后,再容忍几轮(比如 5 轮)没提升就停止训练,避免模型 “学太细”(死记训练集),停在泛化能力最强的节点 )防止过拟合


