机器翻译实战(英译汉)Transformer代码学习详解

任务目标

基于Transformer实现英语翻译汉语。如有疏忽请多指教

数据

Hi.	嗨。
Hi.	你好。
Run.	你用跑的。
Wait!	等等!
Hello!	你好。
I try.	让我来。
I won!	我赢了。
Oh no!	不会吧。
Cheers!	乾杯!
Got it?	你懂了吗?
He ran.	他跑了。
Hop in.	跳进来。
I lost.	我迷失了。
I quit.	我退出。
I'm OK.	我沒事。
Listen.	听着。
No way!	不可能!
No way!	没门!
Really?	你确定?
Try it.	试试吧。
We try.	我们来试试。
Why me?	为什么是我?
……     ……

代码&数据来源

Github:transformer-simple
哈弗NLP

Transformer模型结构

Transformer的组成
    1. Encoder
        a. 若干个EncoderLayer(两个子层)
            i. Feed Forward Neural Network
            connected layer.子层间使用Add & Normalization 相连
            ii. Self-Attention
    2. Decoder
        a. 若干个DecoderLayer(三个子层)
            i. Feed Forward Neural Network
            connected layer.子层间使用Add & Normalization 相连
            ii. Encoder-Decoder-Attention,常规注意力机制
            connected layer.子层间使用Add & Normalization 相连
            iii. Self-Attention,自注意力机制

在这里插入图片描述

Batch and Masking

Mask策略一

一种就是普通的mask,就是自然语言处理中将某些字符(如标点符号,空格等)进行mask的操作

# 该部分与transformer实现有关
class Batch:
    """
    Batches and Masking
    "Object for holding a batch of data with mask during training." 在训练期间使用mask处理数据
    """
    def __init__(self, src, trg=None, pad=0):
        """
        构造函数
        @param src: 源数据
        @param trg: 目标数据
        @param pad: 需要mask掉的字符,默认为0
        一共有两种mask的方式:
        一种就是普通的mask,就是自然语言处理中将某些字符(如标点符号,空格等)进行mask的操作
        另一种就是对目标数据的mask,其原因是为了不让decoder在训练中看到后续的内容(即,我对于下一个字符的预测,只来源于前面的字符)
        对于src的mask就是第一种mask,而对于tgt的mask是第一种加第二种
        """
        # 将numpy.array转换为张量torch.tensor
        src = torch.from_numpy(src).to(args.device).long()
        trg = torch.from_numpy(trg).to(args.device).long()

        self.src = src
        # 此处pad=0,src向量均不为0(0表示UNK标识),src!=pad生成bool数组,且数组所有元素均为True
        # 此处为第一种mask策略
        self.src_mask = (src != pad).unsqueeze(-2) # unsqueeze()扩展维度,负数表示扩展的维度在倒数第n个位置
        if trg is not None:
            self.trg = trg[:, :-1]  # 截掉trg中每个句子最后一个字符<EOS>
            self.trg_y = trg[:, 1:]  # 截掉trg中每个句子第一个字符<BOS>
            self.trg_mask = self.make_std_mask(self.trg, pad)  # 对trg掩蔽
            self.ntokens = (self.trg_y != pad).data.sum()

    @staticmethod
    def make_std_mask(tgt, pad):
        """
        mask 目标数据
        "Create a mask to hide padding and future words." 翻译:创造一个mask来屏蔽补全词和字典外的词进行屏蔽
        @param tgt: 即构造函数中的trg,目标数据
        @param pad: 需要mask的字符,默认为0
        @return: 返回mask后的目标数据
        """
        # 此处为第一种mask策略
        tgt_mask = (tgt != pad).unsqueeze(-2)  # 由于没有0,此时布尔矩阵全为True
        # 此处为第二种mask策略,调用utils中的subsequent_mask方法得到上三角布尔矩阵
        # Variable()封装tensor,并存储tensor的梯度,与tgt_mask做与运算
        tgt_mask = tgt_mask & Variable(subsequent_mask(tgt.size(-1)).type_as(tgt_mask.data))
        return tgt_mask

Mask策略二

另一种就是对目标数据的mask,其原因是为了不让decoder在训练中看到后续的内容(即,我对于下一个字符的预测,只来源于前面的字符)

def subsequent_mask(size):
    """
    第二种mask策略
    "Mask out subsequent positions."
    @param size: 句子长度
    @return:
    """
    attn_shape = (1, size, size)
    # np.triu函数生成一个对角线位置上移一位的上三角矩阵(k=1代表按对角线方向上移),矩阵大小为attn_shape
    subsequent_mask = np.triu(np.ones(attn_shape), k=1).astype('uint8')
    return torch.from_numpy(subsequent_mask) == 0  # 返回布尔矩阵,subsequent_mask上三角矩阵中0的位置对应True

make_model

构造Transformer模型

def make_model(src_vocab, tgt_vocab, N = 6, d_model = 512, d_ff = 2048, h = 8, dropout = 0.1):
    """
    定义了一个接收超参数并生成完整模型的函数。
    @param src_vocab: 源数据字典长度
    @param tgt_vocab: 目标数据字典长度
    @param N: 层数layer
    @param d_model: 表征后的维度
    @param d_ff: FeedForward输出维度
    @param h: attention机制,head多头个数
    @param dropout:
    @return:
    """
    c = copy.deepcopy
    attn = MultiHeadedAttention(h, d_model).to(args.device)  # 多头注意力机制
    ff = PositionwiseFeedForward(d_model, d_ff, dropout).to(args.device)
    position = PositionalEncoding(d_model, dropout).to(args.device)  # 位置信息嵌入
    # model其实是Transformer的类
    model = Transformer(
        Encoder(EncoderLayer(d_model, c(attn), c(ff), dropout).to(args.device), N).to(args.device),
        Decoder(</
  • 19
    点赞
  • 195
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
Transformer是一种用于机器翻译任务的神经网络结构。它在2017年被提出,并且在翻译效果和训练效率方面取得了显著的突破。相比于传统的基于循环神经网络(RNN)的模型Transformer采用了自注意力机制(self-attention)来捕捉输入序列中的上下文信息,从而更好地建模长距离依赖关系。此外,Transformer还引入了位置编码(position encoding)来处理输入序列的顺序信息。 下面是一个使用Transformer进行英译汉的示例: ```python import torch from torch import nn from torch.nn import Transformer # 定义Transformer模型 class TransformerTranslator(nn.Module): def __init__(self, src_vocab_size, tgt_vocab_size, d_model, nhead, num_layers): super(TransformerTranslator, self).__init__() self.embedding = nn.Embedding(src_vocab_size, d_model) self.transformer = Transformer(d_model, nhead, num_layers) self.fc = nn.Linear(d_model, tgt_vocab_size) def forward(self, src): src_embedded = self.embedding(src) output = self.transformer(src_embedded) output = self.fc(output) return output # 创建模型实例 src_vocab_size = 10000 # 源语言词汇表大小 tgt_vocab_size = 5000 # 目标语言词汇表大小 d_model = 512 # 模型维度 nhead = 8 # 注意力头数 num_layers = 6 # 编码器和解码器层数 model = TransformerTranslator(src_vocab_size, tgt_vocab_size, d_model, nhead, num_layers) # 加载预训练模型参数 model.load_state_dict(torch.load("transformer_model.pth")) # 准备输入数据 src_sentence = "Hello, how are you?" src_tokens = [token2id[token] for token in src_sentence.split()] src_tensor = torch.tensor(src_tokens).unsqueeze(0) # 添加batch维度 # 使用模型进行翻译 output = model(src_tensor) output_tokens = output.argmax(dim=-1).squeeze().tolist() tgt_sentence = " ".join([id2token[token] for token in output_tokens]) print("Translation:", tgt_sentence) ``` 这是一个简单的示例,实际使用中还需要进行数据预处理、模型训练等步骤。如果你想深入了解Transformer的细节和更多应用,请参考引用和引用中提供的文献。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值