学习了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 会输出两部分:

  1. 句子里每个词的特征向量
  2. 句首特殊符号 **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 轮)没提升就停止训练,避免模型 “学太细”(死记训练集),停在泛化能力最强的节点 )防止过拟合