Convolutional Sequence to Sequence Learning
机器翻译(Machine Translation)是利用计算机将一种自然语言(源语言)转换为另一种自然语言(目标语言)的过程,输入为源语言句子,输出为相应的目标语言的句子。
本项目是基于卷积的机器翻译模型ConvS2S的PaddlePaddle 实现,该模型不仅能并行计算,还可以通过层叠的方式捕捉长距离依赖关系。
公开数据集:WMT 翻译大赛是机器翻译领域最具权威的国际评测大赛,其中英罗马翻译任务提供了一个中等规模的数据集,这个数据集是较多论文中使用的数据集,也是 ConvS2S 论文中用到的一个数据集。本项目使用WMT'16 EN-RO 数据集作为示例提供。
英罗马数据集共2.86M训练集,1999条测试集。本项目已采用bpe分词处理好,把共现概率最高的字符相连成子词。
en-ro处理脚本:https://github.com/rsennrich/wmt16-scripts/blob/80e21e5/sample/preprocess.sh
backtranslation数据:http://data.statmt.org/rsennrich/wmt16_backtranslations/en-ro
处理好的wmt16_enro:https://aistudio.baidu.com/aistudio/datasetdetail/126881
- 整体结构: ConvS2S是经典的encoder、decoder的结构,分别堆叠了多层卷积块。上图中上面的是encoder的结构(嵌入和一个卷积块),最下面是decoder的结构,中间的矩形代表decoder的某层与encoder的输出进行多步注意力,具体为:
- embed:encoder、decoder分别有个嵌入层,包含词嵌入和位置嵌入,分别得到w和p,将两者相加得到嵌入表示e。
- conv block:encoder、decoder的卷积块结构相同,基本上都是核为3的一维卷积,通道为输入通道数d的两倍2d,并使用门控线性函数(GLU)将一半通道的输出作为门控,从另一半中抽取需要的时序信息,最终还是得到d维的通道。除此之外,末尾几层通道数会变大,与上一层输出作残差连接时需要用线性层把输入e扩展到相应通道数。
- multi step attention: 多步注意力即decoder每层输出hi都和encoder输出z做注意力计算,然后用注意力权重抽取encoder的z+e的信息,得到上下文向量c,与当前decoder层的输出hi相加得到hi+c,或者作为decoder下一层输入,或者用proj得到batch*vocab_size的logits,用以表示输出的词
- 模型特点:
- 采用卷积结构,复杂度低:n个词,卷积核宽为k,复杂度为O(n/k),而循环神经网络复杂度为O(n)。速度非常快,能够并行训练。
- 通过堆叠多层卷积,可以扩大感受野,从而捕获长距离的依赖关系,从而用卷积作时序任务。
# 克隆至本地
git clone https://github.com/MiuGod0126/ConvS2S_Paddle.git
cd ConvS2S_Paddle
# 安装依赖
pip install -r requirements
# 准备数据(wmt16_enro_bpe内已包含训练100对、验证、测试各1000对)
mkdir model_best
# 将权重文件拷贝到./model_best,权重见第5节链接
如果想要处理自己的翻译数据,以俄中为例,先将数据组织成如下形式,然后运行命令:
# src=ru tgt=zh
├── ruzh/
│ ├── train.ru
│ └── train.zh
│ └── dev.ru-zh.ru # dev.src-tgt.src,验证集有时含两个方向,继续添加为dev.tgt-src.src
│ └── dev.ru-zh.ru
│ └── test.ru-zh.ru # test.src-tgt.src,测试集有时也含两个方向,继续添加为test.tgt-src.src
│ └── test.ru-zh.zh
#运行处理脚本
bash ./scripts/preprocess.sh ./ruzh ./ruzh_bpe ru zh 40000 #(in_dir out_dir src tgt bpe_operations)
├── wmt16_enro_bpe # 数据
├── model_best # 权重文件
├── README.md
├── align.py # 对齐
├── ckpt # 权重
├── config.py #命令行参数
├── config #配置
│ ├── en2de.yaml #英德
│ └── en2ro.yaml #英罗马
├── data
│ ├── data.py # 数据加载
│ └── sampler.py # 采样器
├── logs # 日志
│ ├── vislogs # 训练曲线
├── valid.py # 模型验证
├── main.py # 主函数
├── main_multi_gpu.py #多卡训练脚本
├── models #模型文件
├── generate.py # 生成翻译并评估
├── requirements.txt # 依赖
以提供的英罗马翻译数据为例,可以执行如下命令进行模型训练:
# 单卡或多卡训练(设置ngpus)
python main_multi_gpu.py --cfg configs/en2ro.yaml \
--amp \
--ngpus 4 \
--accum-iter 4 \
--max-epoch 100 \
--save-epoch 5 \
--save-dir /root/paddlejob/workspace/output \
--resume '' \
--last-epoch 0 \
--log-steps 100 \
--max-tokens 4000 \
--lr 0.5 \
--lr-shrink 0.9 \
--patience 1
#或
bash ./scripts/run.sh
# 模型验证
python main_multi_gpu.py --cfg configs/en2ro.yaml --pretrained ./model_best --eval
可以在 configs/en2ro.yaml
件中设置相应的参数,如果要恢复训练需指定恢复的轮数last_epoch,和恢复的权重路径resume,其他参数详见yaml文件。
以英罗马翻译数据为例,模型训练完成后可以执行以下命令对指定文件中的文本进行翻译,默认将翻译结果打印在终端,若要保存到文件,设置generate-path和sorted-path参数:
python generate.py --cfg configs/en2ro.yaml \ # 配置文件
--test-pref wmt16_enro_bpe/test \ #测试文件前缀
--only-src \ #无tgt文件
--pretrained ./model_best \ #权重
--beam-size 5 \ # 术搜索宽度
--generate-path generate.txt \ # 源文、目标文、预测结果(乱序)
--sorted-path result.txt # 翻译结果(顺序)
#或
bash ./scripts/generate.sh
训练、验证曲线使用visualdl生成,命令为:
visualdl --logdir ./logs/vislogs --port 8080
# 打开链接:localhost:8080
在enro数据集上训练了23个epoch,bleu对比如下:
Code | Bleu |
---|---|
fairseq | 30.02 |
this repo | 29.98 |
- enro数据链接:https://aistudio.baidu.com/aistudio/datasetdetail/126881
- 权重(enro)链接:https://pan.baidu.com/s/1gZGl_KQTgSNV9txE3TQMjQ 提取码:s8np
- aistudio:https://aistudio.baidu.com/aistudio/projectdetail/2328014