当前位置:   article > 正文

基于术语词典干预的机器翻译挑战赛(Transformer)[ Datawhale AI 夏令营]

基于术语词典干预的机器翻译挑战赛(Transformer)[ Datawhale AI 夏令营]

赛题情况

具体可以参见该讯飞赛题链接

简单概括来讲该任务就是术语词典干预的机器翻译:选择以英文为源语言,中文为目标语言的机器翻译。本次大赛除英文到中文的双语数据,还提供英中对照的术语词典。

即利用提供的训练数据样本构建与训练机器翻译模型,并基于测试集以及术语词典,提供最终的翻译结果,数据包括:

训练集(Training):双语数据:中英14万余双语句对
开发集(也叫验证集,Validation):英中1000双语句对
测试集(Testing):英中1000双语句对
术语词典:英中2226条

关于Transformer

Transformer来源于谷歌团队的“Attention Is All You Need”文章,就是这篇文章提出了大名鼎鼎的Transformer网络结构,如下图1所示。

论文里的Transformer架构

图1: 论文里的Transformer架构

Transformer架构中主要有以下几个核心:位置编码(Positional Encoding)、多头注意力(Multiple Attention)、残差连接(Residual Connections)等。下面将简单介绍一下:

位置编码(Positional Encoding)

位置编码(位置嵌入)的计算过程如下:

P E ( O d d ) = sin ⁡ ( p o s / 1000 0 2 i / d i m ) P E ( O d d ) = \sin ( p o s / 1 0 0 0 0 ^ { 2 i / d i m } ) PE(Odd)=sin(pos/100002i/dim)

P E ( E v e n ) = cos ⁡ ( p o s / 1000 0 2 i / d i m ) P E ( E v e n ) = \cos ( p o s / 1 0 0 0 0 ^ { 2 i / d i m } ) PE(Even)=cos(pos/100002i/dim)

其中 p o s pos pos为单词所在的位置( p o s = 0 , 1 , 2 , 3 , … pos=0,1,2,3,\dots pos=0,1,2,3,), i i i E m b e d d i n g Embedding Embedding数组中的索引下标,同时 i i i的奇偶决定了 O d d Odd Odd还是 E v e n Even Even计算, d i m dim dim为嵌入向量的维度。

这里举一个简单的例子(详细过程可以参考知乎该博主):
以 When you play game of thrones中的When为例,如下图2(详细过程可以参考知乎该博主):
在这里插入图片描述

图2: 位置编码的简单例子(1)

生成位置编码后,可与原始单词编码结合起来,如下图3(详细过程可以参考知乎该博主):
在这里插入图片描述

图3: 位置编码的简单例子(2)

即如下图4所示(详细过程可以参考知乎该博主):
在这里插入图片描述

图4: 位置编码的简单例子(3)

多头注意力(Multiple Attention)

注意力机制的关键在于以下参数 K ( K e y ) K(Key) KKey Q ( Q u e r y ) Q(Query) QQuery V ( V a l u e ) V(Value) VValue

可以这样理解,V 是我们手头已经有的所有资料,可以作为一个知识库;Q 是我们待查询的东西,我们希望把V中和Q有关的信息都找出来而 K是V 这个知识库的钥匙 ,V中每个位置的信息对应于一个K 。对于V中的每个位置的信息而言,如果 Q和对应钥匙 的匹配程度越高,那么就可以从该条信息中找到和Q 更多的内容。

继续以When you play game of thrones为例:
在这里插入图片描述

图 5:多头注意力地简单例子(1)

其中,初始的Linear weights矩阵随机生成,并一般通过反向传播等算法调整权重。

在这里插入图片描述

图 6:多头注意力地简单例子(2)

在这里插入图片描述

图 7:多头注意力地简单例子(3)

再通过Q与K矩阵乘法,缩放点积和归一化即可得到结果:
在这里插入图片描述

图 8:多头注意力地简单例子(4)

最后再把上述结果与V相乘。
在这里插入图片描述

图 9:多头注意力地简单例子(5)

经过该操作后,我们只得到了其中的一头注意力结果,对该操作重复,即可得到多头结果,最终将他们拼接:
在这里插入图片描述

图 10:多头注意力地简单例子(6)

残差连接(Residual Connections)

随着网络层的深度的增加,网络更深层保留的原始信息减少,为了保持信息的不丢失,通过残差连接可以很好地保留该特点。

此外,残差连接还可以一定程度解决梯度消失问题。

赛题代码模块

借助于Pytorch模块,可以快速搭建模型架构。

核心Transformer模块

class PositionalEncoding(nn.Module):
    # 位置编码,d_model为词嵌入维度,dropout为dropout概率,max_len为最大长度
    def __init__(self, d_model, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        # dropout层
        self.dropout = nn.Dropout(p=dropout)
        # 初始化一个位置编码矩阵
        pe = torch.zeros(max_len, d_model)
        # 初始化位置
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        # 计算位置编码
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
        # 计算位置编码矩阵
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0).transpose(0, 1)
        # 初始化位置编码矩阵,然后增加一个维度,这样可以直接与输入张量相加
        self.register_buffer('pe', pe)

    def forward(self, x):
        # 位置编码矩阵与输入张量相加
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)

class TransformerModel(nn.Module):
    # Transformer,src为源语言词汇表,tgt为目标语言词汇表,d_model为词嵌入维度,nhead为头数,num_encoder_layers为编码器层数,num_decoder_layers为解码器层数,dim_feedforward为前馈神经网络维度,dropout为dropout概率
    def __init__(self, src_vocab, tgt_vocab, d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout):
        super(TransformerModel, self).__init__()
        # 初始化一个Transformer模型
        self.transformer = nn.Transformer(d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout)
        # 初始化位置编码
        self.src_embedding = nn.Embedding(len(src_vocab), d_model)
        self.tgt_embedding = nn.Embedding(len(tgt_vocab), d_model)
        self.positional_encoding = PositionalEncoding(d_model, dropout)
        # 输出层
        self.fc_out = nn.Linear(d_model, len(tgt_vocab))
        # 初始化参数
        self.src_vocab = src_vocab
        self.tgt_vocab = tgt_vocab
        self.d_model = d_model

    def forward(self, src, tgt):
        # 调整src和tgt的维度
        src = src.transpose(0, 1)  # (seq_len, batch_size)
        tgt = tgt.transpose(0, 1)  # (seq_len, batch_size)
        # 生成mask
        src_mask = self.transformer.generate_square_subsequent_mask(src.size(0)).to(src.device)
        tgt_mask = self.transformer.generate_square_subsequent_mask(tgt.size(0)).to(tgt.device)
        # 生成padding mask
        src_padding_mask = (src == self.src_vocab['<pad>']).transpose(0, 1)
        tgt_padding_mask = (tgt == self.tgt_vocab['<pad>']).transpose(0, 1)

        src_embedded = self.positional_encoding(self.src_embedding(src) * math.sqrt(self.d_model))
        tgt_embedded = self.positional_encoding(self.tgt_embedding(tgt) * math.sqrt(self.d_model))

        output = self.transformer(src_embedded, tgt_embedded,
                                  src_mask, tgt_mask, None, src_padding_mask, tgt_padding_mask, src_padding_mask)
        return self.fc_out(output).transpose(0, 1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

参考资料

[1].基于术语词典干预的机器翻译挑战赛
[2].从编解码和词嵌入开始,一步一步理解Transformer,注意力机制(Attention)的本质是卷积神经网络(CNN)
[3].三万字最全解析!从零实现Transformer(小白必会版

推荐阅读
相关标签