1.pytorch attentionԴ?源码?
2.大模型中常用的注意力机制GQA详解以及Pytorch代码实现
3.PyTorch中torch.nn.Transformer的源码解读(自顶向下视角)
4.双向LSTM+Attention文本分类模型(附pytorch代码)
5.BERT:一切过往, 皆为序章BERT预训练模型 | 10分钟理解Bert | Pytorch代码讲解 | 代码可运行
6.带你认识self-attention
pytorch attentionԴ?源码?
本文旨在介绍注意力机制(Attention mechanism)、多头注意力(Multi-head attention)、源码自注意力(self-attention)及其在Pytorch中的源码实现,文章内容严格遵循上述要求。源码
一、源码源码转十进制需要符号吗注意力机制(Attention mechanism)
注意力机制的源码核心在于将输入的query与key值对映射到输出,其中query、源码key、源码value均以向量形式表示。源码计算时,源码首先评估query与每个key的源码关联性(compatibility),以该关联性作为value的源码权重(weight)。随后,源码各权重与相应的源码value进行乘积相加,形成输出。
以厨房中的物品为例,假设我们有一个“红色”的query,厨房里有苹果、青菜、西红柿、玛瑙筷子、朱砂碗等物品,每个物品对应一个key([公式]维向量)和value([公式]维向量)。通过计算“红色”query与各物品key的关联性,获得各物品对应的权重,并计算输出。苹果和西红柿因与“红色”关联性更高,对最终输出影响更大。二、多头注意力(Multi-head attention)
单头注意力仅计算一次注意力过程,而多头注意力则是对同一Q、K、V求多次注意力,得到多个不同的输出,最终将这些输出连接起来形成最终输出。其主要作用在于从不同层面(representation subspace)综合考虑关联性,从而获取更全面的信息。
假设以“红色”为query,多头注意力可以分为不同头部(例如从食物层面、餐具层面考虑),得到的输出分别受到苹果、西红柿与玛瑙筷子、朱砂碗的影响。相比单头注意力,多头注意力能考虑更多层面的信息,实现更丰富的信息融合。三、钱袋子自编源码自注意力(self-attention)
当query、key、value都来源于同一输入时,即为自注意力。以厨房中的物品为例,每个物品都会计算得到一个query、key和value,这些值用于评估与其他物品之间的关联性,从而形成最终的输出。这样,输入的每个物品通过不同的表示形式(输出)被重新表示,同时考虑了所有物品的信息。
四、mask的设置
对于self-attention,mask通常用于控制注意力机制的计算范围,如避免自我关注(即让模型忽略自身向量与其他向量之间的交互)。设置mask时,通常将对角线上的值设为0,其余值设为1,以此限制模型在计算时只关注非对角线上的元素。
五、Demo
由于文章篇幅限制,未提供具体实现代码。在实际应用中,Pytorch框架提供丰富的API和模块,如torch.nn包中的MultiheadAttention类,用于实现多头注意力。对于自注意力与注意力机制的实现,同样可以借助Pytorch提供的工具进行。
大模型中常用的注意力机制GQA详解以及Pytorch代码实现
分组查询注意力 (Grouped Query Attention) 是一种结合多查询注意力 (MQA) 和多头注意力 (MHA) 的方法。它旨在保持 MQA 的高效性同时实现 MHA 的质量。GQA 在论文 GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints 中提出。GQA 在多头注意力之上构建,将查询头分为 G 组,每组共享键和值。
标准多头注意力由 H 个查询头、键头和值头组成,每个头有 D 维度。在 Pytorch 中,MHA 可通过以下代码实现:
每个查询头对应一个键,其过程如下图所示。GQA 将查询头分为 G 组,以提高 MQA 的速度并实现 MHA 的质量。
使用可视化表示,GQA 简洁明了。代码如下,使用了 einops 库简化了张量操作:
定义查询、拖拽html制作源码键和值,设置注意力头数量,确保 num_heads_for_query 可被 num_heads_for_key 整除。然后,交换 seq_len 和 num_heads 维度,einops 可以简化这一过程。引入 “分组” 概念,使用 einops 重塑查询矩阵。最后,使用 einsum 进行矩阵乘法和维度求和,完成注意力分数计算。
代码实现如下,总行数不到 行:
MQA 是另一种简化 MHA 的流行方法,所有查询共享相同的键和值。GQA 可以视为 MQA 和 MHA 的权衡,实现最佳性能与模型质量之间的平衡。
使用 GQA,可以达到与 MHA 类似的模型质量,同时将处理时间提高 3 倍,相当于 MQA 的性能。对于高负载系统而言,这至关重要。Pytorch 中没有 GQA 的官方实现,但有一个比较好的非官方实现可供参考。
参考资料:
论文链接:arxiv.org/pdf/....
代码实现链接:github.com/fkodom/group...
PyTorch中torch.nn.Transformer的源码解读(自顶向下视角)
torch.nn.Transformer是PyTorch中实现Transformer模型的类,其设计基于论文"Attention is All You Need"。本文尝试从官方文档和代码示例入手,解析torch.nn.Transformer源码。
在官方文档中,对于torch.nn.Transformer的介绍相对简略,欲深入了解每个参数(特别是各种mask参数)的用法,建议参考基于torch.nn.Transformer实现的seq2seq任务的vanilla-transformer项目。
Transformer类实现了模型架构的核心部分,包括初始化和forward函数。初始化时,主要初始化encoder和decoder,其中encoder通过重复堆叠TransformerEncoderLayer实现,decoder初始化类似。forward函数依次调用encoder和decoder,encoder的输出作为decoder的输入。
TransformerEncoder初始化包括设置encoder_layer和num_layers,用于创建重复的encoder层。forward函数则调用这些层进行数据处理,输出编码后的结果。
TransformerEncoderLayer实现了论文中红框部分的结构,包含SelfAttention和FeedForward层。初始化时,书本自动翻页源码主要设置层的参数,forward函数调用这些层进行数据处理。
在实现细节中,可以进一步探索MultiheadAttention的实现,包括初始化和forward函数。初始化涉及QKV的投影矩阵,forward函数调用F.multi_head_attention_forward进行数据处理。
F.multi_head_attention_forward分为三部分:in-projection、scaled_dot_product_attention和拼接变换。in-projection进行线性变换,scaled_dot_product_attention计算注意力权重,拼接变换则将处理后的结果整合。
TransformerDecoder和TransformerDecoderLayer的实现与TransformerEncoder相似,但多了一个mha_block,用于处理多头注意力。
总结,torch.nn.Transformer遵循论文设计,代码量适中,结构清晰,便于快速理解Transformer模型架构。通过自顶向下的解析,可以深入理解其内部实现。
双向LSTM+Attention文本分类模型(附pytorch代码)
深度学习中的注意力模型(Attention Model)模仿了人脑在处理信息时的注意力机制。在阅读文本时,虽然我们能整体看到文字,但注意力往往集中在特定的词语上,这意味着大脑对信息的处理是具有差异性的。这种差异性权重分配的核心思想在深度学习领域被广泛应用。要深入了解这一模型的原理,可以参考相关论文。
在文本分类任务中,结合传统LSTM(Long Short-Term Memory)模型,双向LSTM+Attention模型可以显著提升分类性能。这种模型架构能够通过注意力机制聚焦文本中的关键信息,从而在分类决策时给予重要性。具体的双向LSTM+Attention模型结构如下所示:
- 双向LSTM模型同时从正向和反向两个方向对输入序列进行处理,捕捉前后文信息;
- Attention机制在双向LSTM输出上应用,动态计算不同位置的权重,聚焦于最具代表性的信息;
- 最终通过全连接层和其他层进行分类决策。
为了展示这一模型的实现,我将具体的代码上传至GitHub,欢迎各位下载研究。代码中包含了多条训练和测试数据,涵盖了6个不同的类别标签。模型使用随机初始化的词向量,最终的准确率稳定在%左右。
本文主要关注model.py文件中的闪烁魂器源码代码实现,具体如下:
- 模型构建主要通过attention_net函数完成,该函数综合了双向LSTM和Attention机制。
注意力模型的计算遵循以下三个公式:
1. 计算上下文向量;
2. 生成注意力权重;
3. 计算加权上下文向量。
代码中详细展示了这三个步骤的实现,同时对每次计算后的张量尺寸进行了注释。为了更直观地理解,避免直接调用torch的softmax函数,代码采用手动实现的方式,清晰展示了softmax计算过程。
在实际应用中,理解并正确实现这些概念对于深度学习工程师来说至关重要。通过这样的模型,我们可以更高效地处理文本数据,提升自然语言处理任务的性能。
BERT:一切过往, 皆为序章BERT预训练模型 | 分钟理解Bert | Pytorch代码讲解 | 代码可运行
前言:
BERT(Bidirectional Encoder Representations from Transformers)是Google AI团队于年推出的一项重大工作,短短几个月内就在文本蕴含识别、语义文本相似度、命名实体识别、自然语言推理等多个领域取得了领先地位。BERT对于深度学习来说,具有划时代的意义。至今,该论文已被引用,次。
1 BERT的结构图
BERT的结构基于Transformer的Encoder部分,对于Transformer的了解可以参考相关文章或原论文。该模型由层Encoder组成,每层结构相似。
2 BERT预训练数据预处理
BERT通过两个自监督任务进行预训练。任务一:判断一对句子是否连续。预处理时,将句子“你好,我是jack”变为“CLS,你,好,SEP,我,是,jack,SEP”,标签为1,表示连续;再从文本中随机选择一句话作为下一句,如“CLS,你,好,SEP,阿,富,汗,独,立,SEP”,标签为0,表示不连续。连续与不连续的句子各占%。任务二:判断被mask掉的词是什么。从句子中随机选择%的词进行mask,其余操作与任务一类似。这两个任务有助于BERT理解语句意思。
预处理后,每个训练数据统一长度,不足部分用“pad”填充,过长数据截断。每个词转化为字典索引表示。
3 BERT的Encoder
3.1 Encoder的输入
输入包含位置、句子信息的词向量,通过三个nn.Embedding()映射到相同维度的高维空间,然后求和作为输入。
3.2 Encoder的encoder
由个encoder组成,以下解释一个encoder。
3.2.1 Self Attention Mechanism
该机制通过计算第一个词与其他每个词的注意力分数,再将分数与对应词信息加权求和,得到与句子中所有词加权和的信息。依次更新每个词的注意力信息。
3.2.2 矩阵思想计算Self Attention Mechanism
通过字向量矩阵与三个矩阵相乘得到注意力值矩阵,经过Softmax计算注意力分数矩阵,并与对应词信息相乘,得到注意力机制输出。
3.2.3 多头注意力机制(Multi-Head Attention)
使用多头注意力机制,将注意力矩阵拆分成多个小矩阵,计算多个注意力信息,最后拼接为输出。
3.2.4 Add & Layer normalization
使用残差网络思想与归一化加速训练。
3.2.5 Feed Forward前馈神经网络
通过两个全连接层实现,与Add & Layer normalization组合。
3.2.6 encoder 输入
前馈神经网络输出作为encoder输入。
4 预训练BERT Pytorch代码
4.1 头文件
4.2 参数设置
4.3 数据预处理
采用动态Mask和动态下句随机匹配,每次迭代数据不同。
4.4 激活函数和归一化
4.5 BertEmbeddings
映射词向量到高维空间。
4.6 Bert Encoder
4.6.1 Encoder的Self-Attention Mechanism
计算注意力分数,加权求和。
4.6.2 Encoder的Add & Layer normalization
使用残差网络和归一化加速训练。
4.6.3 Encoder
组合层Encoder。
4.9 BertPooler(处理CLS信息)
提取Encoder输出的“CLS”特征。
4. 预训练模型加载、保存
4. BertModel
组合所有类。
4. 预训练BertPreTrainingHeads(下游任务)
为预训练做准备。
4. 预训练模型定义
定义模型,计算损失。
4. 训练
展示训练过程中的损失值。
如果有疑问、建议或错误,欢迎留言指正。
带你认识self-attention
Google在年发表的《Attention Is All You Need》论文中,提出了广泛应用于NLP和CV领域的transformer模型,而self-attention是其核心组成部分。传统NLP方法如RNN和LSTM存在计算并行性低及长距离依赖问题,而self-attention通过位置编码实现序列关系,计算上并行,且能避免长距离依赖。
self-attention原理涉及三种NLP任务形式:输出与输出长度一致(如词性识别)、输入与输出长度不一致且输出为单一元素(如文本分类、情绪识别)、输入与输出长度不一致且输出为多个元素(如翻译、文本摘要等)。其关键在于处理不同输入向量间关系和单个输入与整体输入间关系,以及不同输入对输出的贡献。
在self-attention中,不同输入间通过点乘度量相关性,查询向量(Query)与每个单词通过与Wq、Wk做乘法生成,Key与Value分别通过与Wk、Wv生成。信息抽取通过将当前输入与Wv相乘生成V,使用与每个输入的V相乘后的alpha值进行加权求和,突出贡献大的输入信息。
实际应用中,使用Multi-head attention能更全面地关注信息,每个输入向量有多个Q、K、V,每组内部只与同类元素进行计算。对于位置信息的处理,虽然self-attention本身不涉及,但在输入层通过位置编码确保其重要性。
在Pytorch中实现self-attention,关键在于初始化参数矩阵(Wq、Wk、Wv),以及转换矩阵维度以支持multi-head计算。forward函数中,输入经过位置编码和mask处理后,与参数矩阵相乘进行attention计算。
总之,self-attention通过并行计算和多头机制,有效处理了序列数据中的长距离依赖问题,提高了模型的并行性和计算效率,成为现代NLP和CV领域不可或缺的技术。
动手学深度学习Attention Pooling: Nadaraya-Watson Kernel Regression(译文, pytorch)
现在你已经理解了注意力机制在图.1.3框架中的关键组成部分。简单来说,它通过queries和keys的交互实现注意力池化,选择性地聚集values以产生输出。接下来,我们将深入探讨Nadaraya-Watson核回归模型,这是一个展示机器学习注意力机制的实例。
首先,设想一个回归问题:给定输入输出对数据集[公式],目标是预测新的输入[公式]的输出[公式]。通过添加噪声项[公式],我们生成了一个人工数据集,包括个训练样本和个测试样本,训练输入按顺序排列以便于可视化。
初始尝试是使用平均池化,对所有训练输出求平均。然而,Nadaraya-Watson和Watson提出的非参数注意力池化方法更为智能。它根据输入位置对输出[公式]进行加权,利用核函数[公式]。在注意力机制的视角下,我们可以将这种池化理解为根据query[公式]和key[公式]交互分配给value[公式]的权重。
选择高斯核[公式],注意力池化的公式变为[公式]。这意味着,当query[公式]与key[公式]接近时,对应的value[公式]会获得更高的权重。与非参数方法相比,参数化的Nadaraya-Watson模型通过学习参数[公式],使得预测线更为平滑,更接近真实数据。
在实践中,我们利用批矩阵乘法计算minibatch内的注意力加权平均,定义和训练参数化版本的Nadaraya-Watson核回归模型。训练过程中,模型通过对比预测输出和实际标签计算损失,然后反向传播优化参数。
训练后的参数化注意力模型能更好地拟合数据,清晰地展示出注意力权值较高的区域。相比于非参数模型,它在可学习性和参数调整上展现了更佳性能。
seq2seq模型、attention机制的原理与pytorch实现
本文主要内容如下:
完整代码见 seq2seq_with_attention
1. seq2seq与attention
1.1 seq2seq模型
seq2seq模型主要用于解决输入为一个文本序列,输出也为一个文本序列的问题,如机器翻译,问答等。该模型由encoder与decoder组成,均采用LSTM实现。其原理是将源序列通过encoder处理压缩为一个向量,代表源序列,然后将此向量作为decoder的初始状态,decoder根据状态输出所需结果。例如,输入序列"ABC"后,seq2seq模型生成输出序列"WXYZ"。但此方法存在输入序列压缩为向量后,信息丢失的问题,尤其是对于长序列。为缓解此问题,论文[1]中提出将输入序列逆序后输入encoder,这样做的一个insight是对于像机器翻译类的任务,源语言与目标语言的词汇大体上是从前往后按顺序对应的。输入逆序后,encoder最后处理的是第一个词,在最后的压缩向量中越靠前的词的信息可能被保留下来,decoder在处理时会看到更多的序列的前面的信息,从而减小误差累计的问题。
1.2 attention
解决seq2seq模型中信息丢失问题更好的方法是使用attention机制。Transformer模型则完全通过attention机制构造。利用Transformer编码器的BERT开启了大规模预训练模型时代,而利用Transformer解码器的GPT系列则开启了LLM时代,推出了像ChatGPT这样的具有里程碑意义的产品。可以说attention是目前NLP领域最重要的概念之一。
将seq2seq与attention机制结合来自于论文[2]。attention方法的思想是让每个解码的步骤都参考编码器所有时刻的输出而不仅是最后的状态。例如,在汉译英例子中,翻译"I like"后的单词时参考encoder所有时间步的输出。attention机制原理如下:
[公式]
其中,attn表示attention操作,因为attention可以通过不同的方法实现。[公式]表示输入序列词长度。[公式]表示输入序列时间步 [公式] 处的信息对解码器 [公式] 时间步的重要程度。[公式]即为编码器所有时刻对编码器[公式]时刻的权重向量。对编码器所有时刻的状态加权求和即为编码器对解码[公式]时刻的参考信息。
2. seq2seq_with_attention翻译模型的实现
模型与 CSN Winter Assignment 4 一致
2.1 encoder
编码器通过双向LSTM实现,如图2所示。每个时间步的状态[公式]分别由前向和后向状态拼接表示:[公式], [公式]。详细表示如下:
[公式]
将正向最后的状态与反向最后的状态拼接然后做线性变换作为解码器的初始状态:
[公式]
以上操作通过pytorch实现如下:
2.2 decoder
训练时采用teach forcing,即decoder每一步的输入使用上一步的真实标签。本模型中做了一处修改,将上一步的实际输出与上一步的真实标签拼接后作为当前步的实际输入。即
[公式]
其中,[公式]为[公式]步的预测的词的向量表示,[公式]为[公式]步的真实标签的词对应的embedding。
[公式]
其中,[公式] 与 [公式]为上一步的状态。
将decoder的状态[公式]与encoder的状态[公式]进行attention处理。 这里采用乘性attention方法:
[公式]
将attention步骤获取的结果[公式] 与decoder的状态[公式]拼接,然后经过线性变换,tanh激活函数及dropout处理获取最后的输出[公式],将[公式]映射到目标词空间并做softmax,获取每一个词预测概率
[公式]
3. 模型训练
训练代码见 seq2seq_with_attention
4. 模型测试
模型在测试集上一些汉译英示例如下:
[1] Sequence to Sequence Learning with Neural Networks
[2] Neural Machine Translation by Jointly Learning to Align and Translate
本文使用 Zhihu On VSCode 创作并发布
BERT源码逐行解析
解析BERT源码,关键在于理解Tensor的形状,这些我在注释中都做了标注,以来自huggingface的PyTorch版本为例。首先,BertConfig中的参数,如bert-base-uncased,包含了word_embedding、position_embedding和token_type_embedding三部分,它们合成为BertEmbedding,形状为[batch_size, seq_len, hidden_size],如( x x )。
Bert的基石是Multi-head-self-attention,这部分是理解BERT的核心。代码中对相对距离编码有详细注释,通过计算左右端点位置,形成一个[seq_len, seq_len]的相对位置矩阵。接着是BertSelfOutput,执行add和norm操作。
BertAttention则将Self-Attention和Self-Output结合起来。BertIntermediate部分,对应BERT模型中的一个FFN(前馈神经网络)部分,而BertOutput则相当直接。最后,BertLayer就是将这些组件组装成一个完整的层,BERT模型就是由多个这样的层叠加而成的。