Transformer实现以及Pytorch源码解读(四)-Encoder层

这篇具有很好参考价值的文章主要介绍了Transformer实现以及Pytorch源码解读(四)-Encoder层。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Transformer结构图

先放一张原论文中的图。从inputs到Poitional Encoding在前三部分中已经分析清楚,接下来往后分析。
Transformer实现以及Pytorch源码解读(四)-Encoder层

Pytorch中对Transformer的调用

Pytorch将图1中左半部分的神经网络层用一个TransformerEncdoer(encoder_layer,num_layers)类进行封装,该类的传参有两个:TransformerEncoderLayer(encoder_layer)和堆叠的层数(num_layers)。

class Transformer(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, num_class,
                 dim_feedforward=512, num_head=2, num_layers=2, dropout=0.1, max_len=512, activation: str = "relu"):
        super(Transformer, self).__init__()
        # 词嵌入层
        self.embedding_dim = embedding_dim
        self.embeddings = nn.Embedding(vocab_size, embedding_dim)
        #其实max_len可以不用设置的太大,只要比最大句子的长度大一些就行了。
        self.position_embedding = PositionalEncoding(embedding_dim, dropout, max_len)
        # 编码层:使用Transformer
        encoder_layer = nn.TransformerEncoderLayer(hidden_dim, num_head, dim_feedforward, dropout, activation)
        self.transformer = nn.TransformerEncoder(encoder_layer, num_layers)
        # 输出层
        self.output = nn.Linear(hidden_dim, num_class)

    def forward(self, inputs, lengths):
        #注意输入的input,每一列表示一个样本,总共有batch_size列
        inputs = torch.transpose(inputs, 0, 1)
        hidden_states = self.embeddings(inputs)
        hidden_states = self.position_embedding(hidden_states)
        attention_mask = length_to_mask(lengths) == False
        hidden_states = self.transformer(hidden_states, src_key_padding_mask=attention_mask).transpose(0, 1)
        logits = self.output(hidden_states)
        log_probs = F.log_softmax(logits, dim=-1)
        return log_probs

接下来逐一分析涉及到的两个类

TransformerEncdoer类

该类处于目录\site-packages\torch\nn\modules\transformer下。

class TransformerEncoder(Module):
    r"""TransformerEncoder is a stack of N encoder layers

    Args:
        encoder_layer: an instance of the TransformerEncoderLayer() class (required).
        num_layers: the number of sub-encoder-layers in the encoder (required).
        norm: the layer normalization component (optional).

    Examples::
        >>> encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8)
        >>> transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers=6)
        >>> src = torch.rand(10, 32, 512)
        >>> out = transformer_encoder(src)
    """
    __constants__ = ['norm']
    def __init__(self, encoder_layer, num_layers, norm=None):
        super(TransformerEncoder, self).__init__()
        self.layers = _get_clones(encoder_layer, num_layers)
        self.num_layers = num_layers
        self.norm = norm
    def forward(self, src: Tensor, mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None) -> Tensor:
        r"""Pass the input through the encoder layers in turn.
        Args:
            src: the sequence to the encoder (required).
            mask: the mask for the src sequence (optional).
            src_key_padding_mask: the mask for the src keys per batch (optional).
        Shape:
            see the docs in Transformer class.
        """
        output = src
        for mod in self.layers:
            output = mod(output, src_mask=mask, src_key_padding_mask=src_key_padding_mask)
        if self.norm is not None:
            output = self.norm(output)
        return output

可以发现该类比较简单,主要进行的是对堆叠的操作。首先将拿到的encoder_layer通过_get_clones()函数克隆若干份,然后在forward中进行循环的调用。我们可以看下)_get_clones方法的实现:

def _get_clones(module, N):
    return ModuleList([copy.deepcopy(module) for i in range(N)])

可以看出主要是利用copy的deepcopy将模型复制了N份,然后在forward中循环的调用自己。这也说明了TransformerEncoderLayer输入输出的维度必定要一样,可以后文求证。

TransformerEncoderLayer类

class TransformerEncoderLayer(Module):
    r"""TransformerEncoderLayer is made up of self-attn and feedforward network.
    This standard encoder layer is based on the paper "Attention Is All You Need".
    Ashish Vaswani, Noam Shazeer, Niki Parmar, Jakob Uszkoreit, Llion Jones, Aidan N Gomez,
    Lukasz Kaiser, and Illia Polosukhin. 2017. Attention is all you need. In Advances in
    Neural Information Processing Systems, pages 6000-6010. Users may modify or implement
    in a different way during application.

    Args:
        d_model: the number of expected features in the input (required).
        nhead: the number of heads in the multiheadattention models (required).
        dim_feedforward: the dimension of the feedforward network model (default=2048).
        dropout: the dropout value (default=0.1).
        activation: the activation function of the intermediate layer, can be a string
            ("relu" or "gelu") or a unary callable. Default: relu
        layer_norm_eps: the eps value in layer normalization components (default=1e-5).
        batch_first: If ``True``, then the input and output tensors are provided
            as (batch, seq, feature). Default: ``False``.
        norm_first: if ``True``, layer norm is done prior to attention and feedforward
            operations, respectivaly. Otherwise it's done after. Default: ``False`` (after).

    Examples::
        >>> encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8)
        >>> src = torch.rand(10, 32, 512)
        >>> out = encoder_layer(src)

    Alternatively, when ``batch_first`` is ``True``:
        >>> encoder_layer = nn.TransformerEncoderLayer(d_model=512, nhead=8, batch_first=True)
        >>> src = torch.rand(32, 10, 512)
        >>> out = encoder_layer(src)
    """
    __constants__ = ['batch_first', 'norm_first']

    def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1, activation=F.relu,
                 layer_norm_eps=1e-5, batch_first=False, norm_first=False,
                 device=None, dtype=None) -> None:
        factory_kwargs = {'device': device, 'dtype': dtype}
        super(TransformerEncoderLayer, self).__init__()
        self.self_attn = MultiheadAttention(d_model, nhead, dropout=dropout, batch_first=batch_first,
                                            **factory_kwargs)
        # Implementation of Feedforward model
        self.linear1 = Linear(d_model, dim_feedforward, **factory_kwargs)
        self.dropout = Dropout(dropout)
        self.linear2 = Linear(dim_feedforward, d_model, **factory_kwargs)
        self.norm_first = norm_first
        self.norm1 = LayerNorm(d_model, eps=layer_norm_eps, **factory_kwargs)
        self.norm2 = LayerNorm(d_model, eps=layer_norm_eps, **factory_kwargs)
        self.dropout1 = Dropout(dropout)
        self.dropout2 = Dropout(dropout)
        # Legacy string support for activation function.
        if isinstance(activation, str):
            self.activation = _get_activation_fn(activation)
        else:
            self.activation = activation
    def __setstate__(self, state):
        if 'activation' not in state:
            state['activation'] = F.relu
        super(TransformerEncoderLayer, self).__setstate__(state)
    def forward(self, src: Tensor, src_mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None) -> Tensor:
        r"""Pass the input through the encoder layer.

        Args:
            src: the sequence to the encoder layer (required).
            src_mask: the mask for the src sequence (optional).
            src_key_padding_mask: the mask for the src keys per batch (optional).

        Shape:
            see the docs in Transformer class.
        """
        # see Fig. 1 of https://arxiv.org/pdf/2002.04745v1.pdf
        x = src
        if self.norm_first:
            x = x + self._sa_block(self.norm1(x), src_mask, src_key_padding_mask)
            x = x + self._ff_block(self.norm2(x))
        else:
            x = self.norm1(x + self._sa_block(x, src_mask, src_key_padding_mask))
            x = self.norm2(x + self._ff_block(x))

        return x
 # self-attention block
    def _sa_block(self, x: Tensor,
                  attn_mask: Optional[Tensor], key_padding_mask: Optional[Tensor]) -> Tensor:
        x = self.self_attn(x, x, x,
                           attn_mask=attn_mask,
                           key_padding_mask=key_padding_mask,
                           need_weights=False)[0]
        return self.dropout1(x)

    # feed forward block
    def _ff_block(self, x: Tensor) -> Tensor:
        x = self.linear2(self.dropout(self.activation(self.linear1(x))))
        return self.dropout2(x)

先看forward()函数,该函数是对x进行的加操作,所以不会改变x的维度,因此我们前面的假设是成立的,TransformerEncdoer类中堆叠的过程输入输出是一样的维度,并且就是通过for循环连续调用。
其中forward中的下面两行包含了Transformer Encoder层的所有运算逻辑:首先,输入与多头注意力机制的结果相加并输出结果,随后,上层的输出结果加上前向反馈的结果经过一个前向传播层(归一化的前向传播层),输出最终的结果。

x = self.norm1(x + self._sa_block(x, src_mask, src_key_padding_mask))
x = self.norm2(x + self._ff_block(x))

同时为了保持维度的同步,feed forward模块的操作如下:

def _ff_block(self, x: Tensor) -> Tensor:
        x = self.linear2(self.dropout(self.activation(self.linear1(x))))
        return self.dropout2(x)

linear1和linear2的初始化参数如下。结合__off_block操作可以看出,feed forward模块首先将词向量拉伸到dim_feedforward层,随后又用linear2从dim_feedforward层拉伸到原来的词向量维度(d_model)。

 Implementation of Feedforward model
 self.linear1 = Linear(d_model, dim_feedforward, **factory_kwargs)
 self.dropout = Dropout(dropout)
 self.linear2 = Linear(dim_feedforward, d_model, **factory_kwargs)

总结

至此,数据流在Transormer编码层的流动过程已经清晰,除了MultiheadAttention,其他的代码和层的设置都是pytorch中的基本操作,不再详细追踪底层实现。MultiheadAttention的代码实现在下节中进行分析。文章来源地址https://www.toymoban.com/news/detail-426440.html

到了这里,关于Transformer实现以及Pytorch源码解读(四)-Encoder层的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 36k字从Attention解读Transformer及其在Vision中的应用(pytorch版)

    深度学习中的卷积操作:https://blog.csdn.net/zyw2002/article/details/128306697 1.1.1 Encoder-Decoder Encoder-Decoder框架顾名思义也就是 编码-解码框架 ,在NLP中Encoder-Decoder框架主要被用来处理 序列-序列问题 。也就是输入一个序列,生成一个序列的问题。这两个序列可以分别是任意长度。 具体

    2024年02月11日
    浏览(29)
  • 【transformer】自注意力源码解读和复杂度计算

    A t t e n t i o n ( Q , K , V ) = s o f t m a x ( Q K T d k ) V Attention(Q,K,V) = softmax(frac{QK^T}{sqrt{d_k}})V A tt e n t i o n ( Q , K , V ) = so f t ma x ( d k ​ ​ Q K T ​ ) V 其中, Q Q Q 为查询向量, K K K 和 V V V 为键向量和值向量, d k d_k d k ​ 为向量的维度。 Q Q Q 、 K K K 和 V V V 在一般情况下是相同的

    2024年02月10日
    浏览(31)
  • Transformer实战-系列教程21:DETR 源码解读8 损失计算:(SetCriterion类)

    有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 DETR 算法解读 DETR 源码解读1(项目配置/CocoDetection类/ConvertCocoPolysToMask类) DETR 源码解读2(DETR类) DETR 源码解读3(位置编码:Joiner类/PositionEmbeddingSine类)

    2024年02月19日
    浏览(34)
  • Transformer实战-系列教程15:DETR 源码解读2(整体架构:DETR类)

    有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 点我下载源码 DETR 算法解读 DETR 源码解读1(项目配置/CocoDetection类/ConvertCocoPolysToMask类) DETR 源码解读2(DETR类) DETR 源码解读3(位置编码:Joiner类/PositionEmbeddingSine类)

    2024年02月20日
    浏览(32)
  • 挑战Transformer的新架构Mamba解析以及Pytorch复现

    今天我们来详细研究这篇论文“Mamba:具有选择性状态空间的线性时间序列建模” Mamba一直在人工智能界掀起波澜,被吹捧为Transformer的潜在竞争对手。到底是什么让Mamba在拥挤的序列建中脱颖而出? 在介绍之前先简要回顾一下现有的模型 Transformer:以其注意力机制而闻名,其中序

    2024年02月02日
    浏览(36)
  • 深入理解深度学习——Transformer:编码器(Encoder)部分

    分类目录:《深入理解深度学习》总目录 相关文章: ·注意力机制(AttentionMechanism):基础知识 ·注意力机制(AttentionMechanism):注意力汇聚与Nadaraya-Watson核回归 ·注意力机制(AttentionMechanism):注意力评分函数(AttentionScoringFunction) ·注意力机制(AttentionMechanism):Bahda

    2024年02月08日
    浏览(53)
  • 【Transformer系列(1)】encoder(编码器)和decoder(解码器)

    前言 这个专栏我们开始学习transformer,自推出以来transformer在深度学习中占有重要地位,不仅在NLP领域,在CV领域中也被广泛应用,尤其是2021年,transformer在CV领域可谓大杀四方。 在论文的学习之前,我们先来介绍一些专业术语。本篇就让我们先来认识一下encoder和decoder吧!

    2024年03月25日
    浏览(47)
  • transfomer中Decoder和Encoder的base_layer的源码实现

    本专栏主要是深度学习/自动驾驶相关的源码实现,获取全套代码请参考 Encoder和Decoder共同组成transfomer,分别对应图中左右浅绿色框内的部分. Encoder: 目的:将输入的特征图转换为一系列自注意力的输出。 工作原理:首先,通过卷积神经网络(CNN)提取输入图像的特征。然后,

    2024年01月18日
    浏览(37)
  • 【pytorch】ResNet源码解读和基于迁移学习的实战

    “工欲善其事,必先利其器”,掌握ResNet网络有必要先了解其原理和源码。本文分别从原理、源码、运用三个方面出发行文,先对ResNet原理进行阐述,然后对pytorch中的源码进行详细解读,最后再基于迁移学习对模型进行调整、实战。本文若有疏漏、需更正、改进的地方,望读

    2024年02月13日
    浏览(27)
  • Transformer的最简洁pytorch实现

    目录 前言 1. 数据预处理 2. 模型参数 3. Positional Encoding 4. Pad Mask 5. Subsequence Mask 6. ScaledDotProductAttention 7. MultiHeadAttention 8. FeedForward Networks 9. Encoder Layer 10. Encoder 11. Decoder Layer 12. Decoder 13. Transformer 14. 训练 15. 测试 附1:对注意力分头的探究 附2:模型中的数据流动  本文是参考

    2024年02月05日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包