珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完成请收下,刘希媛

频道:国内时事 日期: 浏览:234

机器之心原创

作者:思

想要做个神经机器翻译模型?想要爱旺旺网站做个强壮的 Transformer?搞定这千行 PaddlePaddle 代码你也能够。


现在,无论是从功能、结构仍是业界应用上,Transformer 都有许多无与伦比的优势。本文将介绍 PaddlePaddle 的 Transformer 项目,咱们从项目运用到源码解析带你玩一玩 NMT。只需千行模型代码,Transformer 完结带回家。


其实 PyTorch、TensorFlow 等干流结构都有 Trans干与打一字former 的完结,但假如咱们需求将它们应用到产品中,仍是需求修正许多。


例如谷歌大脑构建的 Tensor2Tensor,它最开端是为了完结 Transformer,后来扩展到了各种使命。关于依据 Tensor2Tensor 完结翻译使命的用户,他们需求在 10 万+行 TensorFl兄长掰弯方案ow 代码找到需求的部分。


PaddlePaddle 供给的 Transformer 完结,项目代码只要 2000+行,简练高雅。假如咱们运用大 Batch Size,那么在猜测速度上,PaddlePaddle 复现的模型比 TensorFlow 官方运用 Tensor2Tensor 完结的模型还要快 4 倍。


项目地址:https://github.com/PaddlePaddle/models/tree/develop/fluid/PaddleNLP/neural_machine_translation/transformer


1. Transformer 怎样用


比较此前 Seq2Seq 模型中广泛运用的循环神经网络,Transformer 运用深层留意力机制取得了更好的效果,现在大多数神经机器翻译模型都选用了这一网络结构。此外,不论是新式的预练习言语模型,仍是问答或句法分析,Transformer 都展现出强壮的建模才干。


比较传统 NMT 运用循环层或卷积层抽取文本信息,Transformer 运用自留意力网络抽取并表征dkgirl这些信息,下图对比了不同层级的特色: 

 

不同网络的首要性质,其间 n 表明山马菜序列长度、d 为隐向量维度、k 为卷积核巨细。例如单层核算复杂度,一般语句长度 n 都小于隐向量维度 d,那么自留意力层级的核算复杂度最小。


如上所示,Transformer 运用的自留意力模型首要具有以下长处,1)网络结构的核算复杂度最低;2)由于序列操作数复杂度低,模型的并行度很高;3)最大途径长度小,能够更好地表明长距离依靠联络;4)模型更简略练习。


现在,假如咱们需求练习一个 Transformer,那么最好的办法是什么?当然是直接跑已复现的模型了,下面咱们将跑一跑 PaddlePaddle 完结的 Transformer。


1.1 处理数据


PaddlePaddle 的复现中,百度选用原论文测验的 WMT'16 EN-DE 数据集,它是一个中等规划的数据集。这儿比较便利的是,百度将数据下载和预处理等进程都放到了 珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛gen_data.sh 脚本中,包含 Tokenize 和 BPE 编码。


在这个项目中,咱们既能够经过脚本预处理数据,也能够运用百度预处理好的数据集。首要最简略的办法是直接运转 gen_data.sh 脚本,运转后能够生成 gen_data 文件夹,该文件夹首要包含以下文件:



其间 wmt16_ende_data_bpe 文件夹包含终究运用的英德翻译数据。


假如咱们从头下载并预处理数据,那么大约需求花 1 到 2 个小时完结预处理。为此,百度也供给了预处理好的 WMT'16 EN-DE 数据集,它包含练习、验证和测验所需求的 BPE 数据和字典。


其间,BPE 战略会把稀少词拆分为高频的子词,这样既能处理低频词无法练习的问题,也能合理下降词表规划。


假如不选用 BPE 的战略,要么词表的规划变得很大,然后使练习速度变慢或许显存太小而无法练习;要么一些低频词会当作未登录词处理,然后得不到练习。


预处理数据地址:https://tra王一淳摘银nsformer-res.bj.bcebos.com/wmt16_ende_data_bpe_clean.tar.gz


假如咱们有其它数据集,例如中英翻译数据,也能够依据特定的格局进行界说。例如用空格分隔不同的 tok格汉药妆en(关于中文而言需求提早用分词东西进行分词),用\t 分隔源言语与方针语句对。


1.2 练习模型


假如需求履行模型练习,咱们也能够直接运转练习主函数 train.py。如下扼要装备了数据途径以及各种模型参数:


# 显存运用的份额,显存缺乏可恰当增大,最大为1
export FLAGS_fraction_of_gpu_memory_to_use=0.8
# 显存整理的阈值,显存不郝宇博士足可恰当减小,最小为0,为负数时不启用
export FLAGS_eager_delete_tensor_gb=0.7
python -u train.py \
  --src_vocab_fpath gen_data/wmt16_ende_data_bpe/vocab_all.bpe.32000 \
  --trg_vocab_fpath gen_data/wmt16_ende_data_bpe/vocab_all.bpe.32000 \
  --special_token '<s>' '<e>' '<unk>' \
  --train_file_pattern gen_data/wmt16_ende_data_bpe/train.tok.clean.bpe.32000.en-de \
  --token_delimiter ' ' \
  --use_token_batch True&华克金是什么东西nbsp;\
  --batch_size 1600 \
  --sort_type pool \
  --pool_size 200000 \
  n_head 8 \
  n_layer 4 \
  d_model 512 \
  邓晶d_inner_hid 1024 \
  prepostprocess_dropout 0.3


此外,假如显存不够大,那么咱们能够将 Batch Size 减小一点。为了快速测验练习珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛效果,咱们将模型调得比 Base Transformer 还小(下降网络的层数、head 的数量、以及隐层的巨细)。


上面仅展现了小部分的超参设置,更多的装备能够在 GitHub 项目 config.py 文件中找到。默许情况下,模型每迭代一万次保存一次模型,每个 epoch 完毕后也会保存一次 cheekpoint。此外,在咱们练习的进程中,默许每一百次迭代会打印一次模型信息,其间 ppl 表明的是困惑度,困惑度越小模型效果越好。


在单机练习中,默许运用一切 GPU,能够经过 CUDA_VISIBLE_DEVICES 环境变量来设置运用的 GPU,例如 CUDA_VISIBLE_DEVICES='0,1',表明运用 0 号和 1 号卡进行练习。


1.3 猜测揣度


练习完 Transformer 后就能够履行揣度了,咱们需求运转对应的揣度文件 infer.py。咱们也能够在揣度进程中装备超参数,但留意超参需求和前面练习时坚持一致。


python -u infer.py \
  --src_vocab_fpath gen_data/wmt16_ende_data_bpe/vocab_all.bpe.32000 \
  --trg_vocab_fpath gen_data/wmt16_ende_data_bpe/vocab_all.bpe.32000 \
  --special_token '<s>' '<e>' '<unk>' \
  --test_file_pattern gen_data/wmt16_ende_data_bpe/newstest2016.tok.珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛bpe.32000.en-de \
  --token_delimiter ' ' \
  --batch_size 32 \
  model_path trained_models/iter_100000.infer.model \
  n_head 8 \
  n_layer 4 \
  d_model 512 \
  d_inner_hid 1024 \
  prepostprocess_dropout 0.3
  beam_size 5 \
  max_out_len 255


比较模型的练习,揣度进程需求一些额定的超参数,例如装备 model_path 指定模型地点目录、设置 beam_size 和 max_out_len 来指定 Beam Search 每一步候选词的个数和最大翻译长度。这些超参数也能够在 config.py 中找到,该文件对这些超参都有注释阐明。


履行以上猜测指令会将翻译成果直接打出来,每行输出是对应行输入得分最高的翻译。关于运用 BPE 的英德数据,猜测出的翻译成果也将是 BPE 表明的数据,所以需求还原成原始数据才干进行正确评价。如下指令能够将 predict.txt 内的翻译成果(BPE 表明)康复到 predict.tok.txt 文件中(tokenize 后的数据):


sed -r 's/(@@ )|(@@ ?$)//g' predict.t武神海啸xt > predict.tok.txt


在未运用集成办法的情况下,百度表明 base model 和 big model 在收敛后,测验集的 BLEU 值参阅如下:



这两个预练习模型也供给了下载地址:


  • Base:https://transformer-res.bj.bcebos.com/base_model.tar.gz

  • Big:https://transformer-res.bj.bcebos.com/big_model.tar.gz


2. Transformer 怎样改


假如咱们想要练习自己的 Transformer,那么又该怎样了解并修正 PaddlePa国贸三期80层餐厅ddle 代码呢?假如咱们需求依据自己的数据集和使命改代码,除了前面数据预处理进程,模型结构等模块有时也需求修正。这就需求咱们先了解源代码了,PaddlePaddle 的源代码根本都是根底的函数或运算,咱们很简略了解并运用。


关于 PaddlePaddle 不熟悉的读者可查阅文档,也能够看看入门教程,了解根本编写形式后就能够看懂整个完结了。


PaddlePaddle 官网地址:http://paddlepaddle.org/paddle


如 Seq2Seq 相同,原版 Transformer 也选用了编码器-解码器结构,但它们会运用多个 Multi-Head 留意力、前馈网络、层级归一化和残差衔接等。下图从左到右展现了原论文所提出的 Transformer 架构、Multi-Head 留意力和标量点乘留意力。



上图右边的点乘留意力便是规范 Seq2Seq 模型中的留意力机制,中心的 Multi-head 留意力其实便是将一个隐层信息切分为多份,并独自核算留意力信息,使得一个词与其它多个方针词的留意力信息核算更准确。最左面为 Transformer 的全体架构,编码器与解码器由多个相似的模块组成,后边将扼要介绍这些模块与对应的 PaddlePaddle 代码。


2.1 点乘留意力


留意力机制现在在机器翻译中现已极端流行了,咱们能够以为 Transformer 是一种堆叠多层留意力网络的模型,它选用的是一种名为经缩放的点乘留意力机制。这种留意力机制运用经缩放的点乘作为作为评分函数,然后评价各躲藏状况对当时猜测的重要性,如下是该留意力的表达式:



其间 Query 向量与 (Key, Value ) 向量在 NMT 中相当于方针语输入序列与源语输入序列,Query 与 Key 向量的点乘,经过 SoftMax 函数后可得出一组归一化的概率。这些概率相当于给源语输入序列做加权均匀,即表明在生成新的隐层信息的时分需求重视哪些词。


在 Transformer 的 PaddlePaddle 完结中,经缩放的点乘留意力是在 Multi-head 留意力函数下完结的,如下所示为上述表达式的完结代码:



在这个函数中,q、k、v 和公式中的相同,attn_bias 用于 Mask 掉选定的特定方位(encode 的 self attention 和 decoder 端的 encode attention 都是屏蔽掉 padding 的词;decoder 的 self attention 屏蔽掉当时词后边的词,意图是为了和解码的进程坚持一致),因而在给不同输入加权时疏忽该方位的输入。


如上 product 核算的是 q 和 k 之间的点乘,且经过根号下 d_key(key 的维度)的缩放。这儿咱们能够发现参数 alpha 能够直接对矩阵乘法的成果进行缩放,默许情况下它为 1.0,即不进行缩放。在 Transformer 原论文中,作者表明假如 d_key 比较小,那么直接点乘和带缩放的点乘不同不大,所以他们以为高维情况下或许不带缩放的乘积太大而令 Softmax 函数饱满。


weights 表明对输入的不同元素加权,即不同输入对当时猜测的重要性,练习中也能够对该权重进行 Dropout。最终 out 表明依照 weights 对输入 V 进行加权和,得出来便是当时留意力蔡壁名的运算成果。


2.2 Muti-head 留意力


Multi-head 留意力其实便是多个点乘留意力并行地处理并最终将成果拼接在一同。一般来说,咱们能够对三个输入矩阵 Q、V、K 别离进行线性改换,然后别离将它们投入 h 个点乘留意力函数并拼接一切的输出成果。


这种留意力答应模型联合重视不同方位的不同表征子空间信息,咱们能够了解为在参数不同享的情况下,屡次履行点乘留意力。如下所示为 Muti-head 留意力的表达式:



其间每一个 head 都为一个点乘留意力,不同 head 的输入是相同 Q、K、V 的不同线性改换。


全体而言,PaddlePaddle 的 Multi-head 留意力完结分为几个进程:先为 Q、K、V 履行线性改换;再改换维度以核算点乘留意力;最终核算各 head 的留意力输出并兼并在一同。


2.2.1 线性改换


如前公式所示,Muti-head 首要要履行线性改换,然后令不同的 head 重视不同表征空间黄荣钢的信息。这种线性改换即乘上不同的权重矩阵,且模型在练习进程中能够学习和更新这些权重矩阵。在如下的 PaddlePaddle 珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛代码中,咱们能够直接调用全衔接层 layers.fc() 完结线性改换。



直接调用全衔接层会主动为输入创立权重,且咱们要求不运用偏置项和激活函数。这儿比较便利的是,PaddlePaddle 的 layers.fc() 函数能够承受高维输入,省掉了手动展平输入向量的操作。因而这儿有 num_flatten_dims=2,行将前两个维度展平为一个维度,第三个维度坚持不变。


例如关于输入张量 q 而言,线性改换的输出维度应该是 [batch_size,max_sequence_length,d_key * n_head],最终一个维度即 n_head 个 d_key 维的 Query 向量。每一个 d_key 维的向量都会馈送到不同的 head,并最终拼接起来。


2.2.2 维度改换


为了进行 Multi-Head 的运算,咱们需求将线性改换的成果进行 reshape 和转置操作。现在咱们将这几个张量的最终一个维度切割成不同的 head,并做转置以便于后续运算。


详细而言,输入张量 q、k 和 v 的维度信息为 [bs, max_sequence_length, n_head * hidden_dim],咱们期望把它们转化为 [bs, n_head, max_sequence_length, hidden_dim]。



如上运用 layers.reshape() 和 layers.transpose() 函数完结切割与转置。其间 layers.reshape() 在接纳输入张量后会依照形状 [0, 0, n_head, d_key] 进行转化,其间 0 表明从输入张量对应维数仿制出来。此外,由于 inplace 设置为 True,那么 reshape 操作就不会进行数据的仿制,然后提高运算功率。


后边的转置就比较简略了,只需求依照维度索引将第「1」个维度和第「2」个维度交流就行了。此外为了更快女诗人邀观众摸胸地履行揣度,PaddlePaddle 完结代码还做了十分多的优化,例如这部分后续会对揣度进程的缓存和处理流程进行优化。


2.2.3 兼并


前面现已介绍过点乘留意力了,那么上面临 q、k、v 履行维度改换后就可直接传入点乘留意力函数,并核算出 head_1、head_2 等留意力成果。现在最终一步只需求将这些 head 拼接起来就完结了整个进程,也就完结了上面 Multi-head 留意力的核算式。


由于每一个批量、head 和时刻步都会核算得出一个留意力向量,因而全体上留意力核算成果的维度信息为 [bs, n_head, max_sequence_length, hidden_dim]。假如要将不同的 head 拼接在一同,行将 head 这个维度兼并到 hidden_dim 中去,因而兼并的进程和前面维度改换的进程正好相反。



如上兼并进程会先查验维度信息,然后先转置再 reshape 兼并不同的 hea珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛d。留意在原论文中,兼并不同的 head 后,还需求再做一个线性改换,这个线性改换的成果便是 Muti-head 留意力的输出了。


最终,咱们再将上面的四部分串起来便是 Transformer 最中心的 Multi-head 留意力。了解了各个模块后,下面串起来就能愉快地看懂整个进程了:



当然,假如编码器和解码器输入到 Multi-head 留意力的 q 与 (k、v) 是相同的珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛,那么它又可称为自留意力网络。


2.3 前馈网络


关于每一个编码器和解码器模块,除了残差衔接与层级归一化外,重要的便是堆叠 Muti-head 留意力和前馈网络(FFN)。前面咱们现已处理了 Multi-head 留意力,现在需求了解主方位的前馈网络了。直观而言,FFN 的效果是整合 Multi-head 留意力生成的上下文向量,因而能更好地运用从源语语句和方针语语句抽取的深度信息。


如下所示在原论文中,前馈网络的核算进程能够表达为以下方程:



前馈网络的结构很简略,一个 ReLU 激活函数加两次线性改换就完结了马化腾与陈碧婷合影。如下根本上只需求调用 PaddlePaddle 的 layers.fc() 就能够了:



现在根本上中心操作就界说完了,后边还有更多模块与架构,例如怎样运用中心操作建立编码器模块与解码器模珍珠奶茶,想要千行代码搞定Transformer?这份高效的PaddlePaddle官方完结请收下,刘希媛块、怎么建立全体 Transformer 模型等,读者可持续阅览原项目中的简练代码。全体而言,包含上面代码在内,千行代码就能够彻底弄懂 Transformer,PaddlePaddle 的 Transformer 复现值得咱们细心读一读。


此外,在这千行模型代码中,为了给练习和揣度加快,还有许多特别技巧。例如在 Decoder 中参加对 Encoder 核算成果的缓存等。加上这波尔卡诺娃些技巧,PaddlePaddle 的完结才干在大 Bat雪之舞第十二套完整版ch Size 下完结 4 倍揣度加快。


由于自身 PaddlePaddle 代码就现已十分精粹,经过它们也很简略了解这些技巧。根本上看函数称号就能知道大致的效果,再结合文档运用就能彻底读懂了。


最终,除了模型架构,整个项目还会有其它组成部分,例如练习、揣度、数据预处理等等。这些代码相同十分简练,咱们能够依据实践需求阅览并修正它们。全体而言,PaddlePaddle 的 Transformer 完结的确十分合适了解与修正。想要跑一跑神经机器翻译的同学,PaddlePaddle 的 Transformer 新抚网完结的确值得引荐。



本文为机器之心原创,转载请联络本大众号取得授权

✄------------------------------------------------

参加机器之心(全职记者 / 实习生):hr@jiqizhixin.com

投稿或寻求报导:content@jiqizhixin.com

广告 & 商务协作:bd@jiqizhixin.com