美文网首页
Transformer详解,输入部分(词嵌入、位置编码)

Transformer详解,输入部分(词嵌入、位置编码)

作者: 三角绿毛怪 | 来源:发表于2021-01-23 23:20 被阅读0次

    Transformer解读

    1.整体架构解读

    image.png

    由图可知:

    1.1输入部分:

    inputs和带标签的输入分别进encoder和decoder

    Positional Encoding

    1.2输出部分

    线性层

    softmax层

    1.3编码器部分

    由N个编码器堆叠而成

    每个编码器有两个子层相连接

    第一个子层->多头自注意力机制和规范化层以及一个残差连接

    第二个子层->全连接层和规范化层以及一个残差连接

    1.4解码器部分

    由N个解码器堆叠而成

    每个编码器有三个子层相连接

    第一个子层->一个多头自注意力机制层和规范化层以及一个残差连接

    第二个子层->多头注意力机制和规范化层以及一个残差连接

    第三个子层->全连接层和规范化层以及一个残差连接

    2.输入部分详解

    2.1Embedding词嵌入

    目的是为了将目标文本的数字表示->向量表示,为了在高维空间捕捉词汇间的关系

    #1.embedding类的实现
    import torch
    from torch.autograd import Variable
    import math
    import torch.nn as nn
    
    class Embeddings(nn.Module):#需要继承
        def __init__(self,d_model,vocab):#词嵌入的维度,词表大小
            super(Embeddings,self).__init__()#继承
            self.lcut = nn.Embedding(vocab,d_model)
            self.d_model = d_model
    
        def forward(self,x):
            """
            可以理解为该层的前向传播逻辑,所有层中都会有此函数。传给类的实例化对象时,自动调用
            :param x:输入进模型的文本通过词汇映射后的数字张量
            :return:
            """
            return self.lcut(x)*math.sqrt(self.d_model)
    

    效果如下

    d_model = 512
    vocab = 100
    x = Variable(torch.LongTensor([[1,2,3,4],[5,6,7,8]]))#[2,4]
    emb = Embeddings(d_model,vocab)
    embr = emb(x)
    print("emb:",embr)
    print(embr.shape)#[2,4,512]
    
    >>>>>
    emb: tensor([[[-13.7408,  -4.3108,  35.0170,  ..., -44.5515, -16.5556,  -2.9577],
             [ 23.3314,  -9.3100,  26.4966,  ...,   7.4887,  28.7678,  16.3725],
             [-13.5485,  28.9699,  35.8271,  ..., -22.9973,  -0.4782,   9.3057],
             [-26.4563,   6.6810, -58.8932,  ...,  55.4734,  16.3932, -38.4998]],
    
            [[  0.6895,  43.8544, -10.3074,  ...,  39.5331,  20.9398,  13.0055],
             [ 10.1109,  16.5785,   7.7799,  ...,  19.8802, -18.9864,  -0.1557],
             [-31.9423,  -5.7930,   2.0319,  ...,   0.4931, -27.7125,  -3.4999],
             [-47.6672,   4.2582, -32.6036,  ...,  12.7451,   9.8043,  -1.6442]]],
           grad_fn=<MulBackward0>)
    torch.Size([2, 4, 512])
    

    2.2Positional Encoding

    2.2.1为什么需要位置编码器(没有上下文关系这种)

    在Transformer编码器中没有针对词汇位置信息的处理,故需要在embedding层后加入位置编码器,将词汇位置不同可能会产生不同语义的信息加入到嵌入张量中(embedding),用来弥补位置信息的缺失。

    2.2.2位置信息编码的实现

    class PositionalEncoding(nn.Module):
        def __init__(self,d_model,dropout,max_len=5000):
            """
            :param d_model:embedding的维度
            :param dropout: Dropout的置零比例
            :param max_len: 每个句子的最大长度
            """
            super(PositionalEncoding, self).__init__()
            #实例化Dropout层
            self.dropout = nn.Dropout(p=dropout)
    
            #初始一个位置编码矩阵,大小是max_len*d_model
            pe = torch.zeros(max_len,d_model)
            #初始化一个绝对位置矩阵,词汇的位置就是用它的索引表示max_len*1
            position = torch.arange(0,max_len).unsqueeze(1)#由[0,1,2...max_len][max_len] -> [[0],[1]...[max_len]][max_len,1]
            #目的是要把position的信息放到pe里面去
    
            #定义一个变换矩阵使得position的[max_len,1]*变换矩阵得到pe[max_len,d_model]->变换矩阵格式[1,d_model]
            #除以这个是为了加快收敛速度
            #div_term格式是[0,1,2...d_model/2],分成了两个部分,步长为2
            div_term = torch.exp(torch.arange(0,d_model,2)*-(math.log(10000.0)/d_model))
            # print(div_term.shape)
            # print(position * div_term)
            # a = position*div_term
            # print(a.shape)
            #将前面定义好的矩阵进行奇数偶数赋值
            pe[:,0::2] = torch.sin(position*div_term)
            pe[:,1::2] = torch.cos(position*div_term)
    
            #此时pe[max_len,d_model]
            #embedding三维(可以是[batch_size,vocab,d_model])#vocab就是max_len
            #将pe升起一个维度扩充成三维张量
            pe = pe.unsqueeze(0)
    
    
            #位置编码矩阵注册成模型的buffer,它不是模型中的参数,不会跟随优化器进行优化
            #注册成buffer后我们就可以在模型的保存和加载时,将这个位置编码器和模型参数加载进来
            self.register_buffer('pe',pe)
    
    
        def forward(self,x):
            """
            :param x:x代表文本序列的词嵌入
            pe编码过长将第二个维度也就是max_len的维度缩小成句子的长度
            """
            x = x + Variable(self.pe[:,:x.size(1)],requires_grad=False)
            return self.dropout(x)
    
    
    x = torch.LongTensor([[1,2,3,4],[5,6,7,8]])#[2,4]
    emb = Embeddings(d_model,vocab)#[2,4,512]
    embr = emb(x)
    pe = PositionalEncoding(d_model,dropout=0.2,max_len=50)
    pe_result = pe(embr)
    #
    print(pe_result)
    print(pe_result.shape)#[2,4,512]
    

    相关文章

      网友评论

          本文标题:Transformer详解,输入部分(词嵌入、位置编码)

          本文链接:https://www.haomeiwen.com/subject/bajpzktx.html