首页 > AI > CPU机器环境上运行FairSeq M2M-100 机器翻译模型
2021
07-15

CPU机器环境上运行FairSeq M2M-100 机器翻译模型

 

 

本指南介绍了在纯 CPU 环境中运行 Facebook FairSeq m2m_100 多语言翻译模型的步骤。 (截至2020年11月)

前言:

截至 2020 年 11 月,FairSeq m2m_100 被认为是最先进的机器翻译模型之一。 它使用基于转换器的模型在任何一对支持的 100 种语言之间进行直接翻译,而无需像大多数机器翻译模型那样通过中间语言(英语)进行路由。 结果是所有翻译基准指标(例如 BLEU 分数)的巨大飞跃。
然而,m2m_100 的问题在于,它们的预训练模型和运行模型所需的源代码都是以需要许多高端 GPU 来执行翻译的方式编写的。 对于大多数开发人员社区的许多 PoC / 开发环境来说,这是不可能的。

 

 

CPU机器环境上运行FairSeq M2M-100 机器翻译模型 - 第1张  | 技术人生

 

 

 

我做了一些研究并调试了 FairSeq 和 m2m_100 的源代码,并成功地修改了源代码/设置以在只有 CPU 的机器上运行 m2m_100 模型。 它仍然需要一台高性能的计算机来运行,因为 m2m_100 模型本身非常大(~51GB)并且需要加载到内存中。 但是通过这种修改,使用 m2m_100 执行翻译的成本比原始要求中需要具有高性能多 GPU 机器的成本低很多。

 

硬件要求:

CPU: X64-based architecture
RAM: 至少 64GB
DISK: 至少 200GB available
GPU: None
OS: Linux (我用的是 Ubuntu 20.04)
SWAP Memory: 至少 128GB, 详见: https://bogdancornianu.com/change-swap-size-in-ubuntu/ for setting up SWAP memory.

 

软件要求:

Python3
Pytorch
由于我们将仅使用 CPU,因此请务必从以下位置安装“No CUDA”版本: https://pytorch.org/get-started/locally/ (我用的版本是1.7.0)
Sentencepiece
您可以使用安装`pip3 install sentencepiece’
Fairscale
您可以使用安装 `pip3 install fairscale==0.1.1’
Fairseq
我们需要最后一个(工作)主分支,因为最新的公共轮仍然没有 m2m_100 模型(截至 2020 年 11 月)。 因此,您需要从以下位置克隆 Fairseq 源代码:
`git clone https://github.com/pytorch/fairseq.git — recursive’
在我写这篇博客时签出到相同的提交版本,以确保源代码修改将在相同的位置并且绝对有效: ‘cd fairseq && git checkout 0d03fbe’
然后使用安装克隆的 FairSeq : ‘pip3 install — editable ./如果您遇到有关没有某些必需库的错误,只需使用“pip3 instal XXXXX”安装它们并再次重新运行安装。

M2m_100 预训练模型权重文件
我使用需要运行 4 个 GPU 的版本 (12b_last_chk_4_gpus.pt)。 你可以从

 
https://github.com/pytorch/fairseq/tree/master/examples/m2m_100 
下载.将预训练的权重文件放在 fairseq 目录中。

 

详细步骤:

我通过调试获得的第一件事是 m2m_100 模型是使用并行模型方法训练的。 这意味着模型被分成多个部分,可以在多个 GPU 上并行运行。 我们需要使用以下参数提供我们想要发送模型部分以运行的 GPU:

— pipeline-encoder-balance '[1,15,10]' \
— pipeline-encoder-devices '[0,1,0]' \
— pipeline-decoder-balance '[3,11,11,1]' \
— pipeline-decoder-devices '[0,2,3,0]'

 

在这里,有必要正确设置设备和平衡的数量(我相信它必须与模型的训练方式相同)否则无法加载预训练的权重(因为张量名称中包含设备和平衡编号)它)。另一个问题是设备的数量是我们要将权重发送到的 GPU 的 ID。 Fairseq 通过使用这些数字作为参数调用 torch.device() 来解析目标 GPU,这是调用函数的传统方式,根本不支持 CPU 目标。 (这个函数的新调用方式是传递像torch.device(‘cuda:0’)这样的参数,可以通过使用torch.deviced(‘cpu’)但是设置[‘cpu’,’cpu’]来支持CPU目标在 m2m_100 输入参数破坏了 FairSeq 的很多部分,需要参数为 number。即使我们安装了 CPU-only 版本的 PyTorch,FairSeq 仍然会尝试使用 GPU(通过直接调用 torch.cuda.XXX 并导致异常被提出。根据所有这些信息,我得出结论,最简单的方法是在参数处理和权重加载后做一个小的修改,以强制每个平衡和设备转到 CPU 而不是 GPU。以下是我所做的修改列表(我添加的行是粗体文本):

 

** 请注意,根据您的 FairSeq 和 Fairscale 库的提交版本,行号可能会有所不同。 最好以函数名和类名为指导,找到更改的位置。

 

1. 仅在模型并行化管道中强制 CPU,无论解析的旧参数如何。

File: fairseq/model_parallel/models/pipeline_parallel_transformer/model.py

Line: 44 — Function: __init__ of class: PipelineParallelTransformerModel

 

class PipelineParallelTransformerModel(BaseFairseqModel):
   def __init__(self, encoder, decoder, balance, devices, chunks, checkpoint):
      devices = ['cpu' for _ in devices]

 

 

2. 您还需要修改 Fairscale 库中的一些代码。

** 取决于您的库安装。 如果你在“venv”环境中安装了所有的库,你可能需要搜索里面的文件

 

<venv dir>/lib/python3.8/site-packages/fairscale
In my case, I installed fairscale globally. So my fairscale is at
.local/lib/python3.8/site-packages/fairscale

 

File: .local/lib/python3.8/site-packages/fairscale/nn/pipe/pipe.py

Line: 318 — Function: split_module

 

if len(layers) == balance[j]:
   # Group buffered layers as a partition.
   partition = nn.Sequential(layers)
   if devices:
      device = devices[j]
      device = torch.device('cpu')
      partition.to(device)

 

Line: 509 — Function: __init__ of class: Pipe

if devices is None:
   devices = range(torch.cuda.device_count())
devices = ['cpu' for d in devices]
devices = [torch.device(d) for d in devices]
devices = cast(List[torch.device], devices)

* 在下面的步骤中,我将演示将泰语翻译成印尼语的命令。 您可以将配置和文件名中的源语言和目标语言从“th”和“id”更改为其他语言。 所有 m2m_100 模型支持的语言对都列在language_pairs.txt

 

准备输入数据。 就我而言,我想将泰语翻译成印尼语。 我会将我所有的泰语输入文本放在“raw_input.th-id.th”中(放在 fairseq 文件夹中)。 奇怪的是,使用 m2m_100 的翻译管道即使不会使用,也需要目标语言原始数据文件。 似乎 m2m_100 会检查并尝试以源语言和目标语言对原始数据进行编码,即使我们进行单向翻译也是如此。 目标原始数据文件也不能为空,因此您可以将任何内容放入其中。 对我来说,我只是将源原始数据复制到目标语言原始数据文件中:‘cp raw_input.th-id.th raw_input.th-id.id’

使用句子模型对原始数据进行编码。 Sentencepiece 是一个分词器模型,它可以使用可变长度的分词合并来生成整个句子。 我创建并运行了一个脚本来完成这样的任务:

File: 1_encode.sh

 

wget https://dl.fbaipublicfiles.com/m2m_100/spm.128k.model
for lang in 'th' 'id'; do
   python3 scripts/spm_encode.py \
      --model spm.128k.model \
      --output_format=piece \
      --inputs=raw_input.th-id.${lang} \
      --outputs=spm.th-id.${lang}
done

 

3.执行我们的输入数据预处理(二进制):

File: 2_binarization.sh

 

wget https://dl.fbaipublicfiles.com/m2m_100/data_dict.128k.txt
fairseq-preprocess \
   --source-lang "th" --target-lang "id" \
   --testpref spm.th-id \
   --thresholdsrc 0 --thresholdtgt 0 \
   --destdir data_bin_th_id \
   --srcdict data_dict.128k.txt --tgtdict data_dict.128k.txt

 

4. 进行翻译。 请注意,我们不能 – fp16 在这里,因为 CPU 不支持像 GPU 那样的半精度浮点数。 您还可以看到,我们需要保留正确的天平和设备参数,以便模型可以正确加载权重文件,然后我们稍后会在修改后的源代码中强制它们进入 CPU。

File: 3_generation_m2m_100.sh

wget https://dl.fbaipublicfiles.com/m2m_100/model_dict.128k.txt
wget https://dl.fbaipublicfiles.com/m2m_100/language_pairs.txt
fairseq-generate \
   data_bin_th_id \
   --cpu \
   --batch-size 1 \
   --path 12b_last_chk_2_gpus.pt \
   --fixed-dictionary model_dict.128k.txt \
   -s "th" -t "id" \
   --remove-bpe 'sentencepiece' \
   --beam 5 \
   --task translation_multi_simple_epoch \
   --lang-pairs language_pairs.txt \
   --decoder-langtok --encoder-langtok src \
   --gen-subset test \
   --dataset-impl mmap \
   --distributed-world-size 1 --distributed-no-spawn \
   --pipeline-chunks 1 \
   --model-overrides '{"ddp_backend": "c10d", "pipeline_balance": "1, 15, 13, 11, 11, 1" , "pipeline_devices": "0, 1, 0, 2, 3, 0" }' \
   --pipeline-encoder-balance '[1,15,10]' \
   --pipeline-encoder-devices '[0,1,0]' \
   --pipeline-decoder-balance '[3,11,11,1]' \
   --pipeline-decoder-devices '[0,2,3,0]' > gen_out

 

5. 可以看到gen_out中写入的结果:

 

S-2 __th__ แถวยาวไปไหม
T-2 แถวยาวไปไหม
H-2 -2.5059561729431152 Berjalan jarak jauh?
D-2 -2.5059561729431152 Berjalan jarak jauh?
P-2 -6.9086 -5.2208 -0.9001 -3.2984 -0.3153 -0.7454 -0.1531
S-1 __th__ พนักงานบริการโคตรแย่
T-1 พนักงานบริการโคตรแย่
H-1 -2.0654807090759277 Pekerja Layanan Kotor
D-1 -2.0654807090759277 Pekerja Layanan Kotor
P-1 -6.4449 -4.4084 -0.6868 -0.2564 -2.1839 -0.1741 -3.2183 -0.6242 -0.5922
S-3 __th__ อยากให้มีพนักงานเยอะกว่านี้
T-3 อยากให้มีพนักงานเยอะกว่านี้
H-3 -1.5292832851409912 Saya ingin lebih banyak karyawan.
D-3 -1.5292832851409912 Saya ingin lebih banyak karyawan.
P-3 -6.1507 -2.1494 -0.7614 -1.5158 -0.2357 -1.2831 -0.1340 -1.3752 -0.1582
S-0 __th__ ทดสอบการใช้ firseq ในการแปลภาษาจากภาษาไทยไปเป็นภาษาอินโดนีเซีย
T-0 ทดสอบการใช้ firseq ในการแปลภาษาจากภาษาไทยไปเป็นภาษาอินโดนีเซีย
H-0 -1.0547080039978027 Uji coba penggunaan firseq dalam terjemahan bahasa Indonesia ke bahasa Indonesia
D-0 -1.0547080039978027 Uji coba penggunaan firseq dalam terjemahan bahasa Indonesia ke bahasa Indonesia
P-0 -4.7732 -1.1226 -0.4373 -1.9382 -1.8837 -0.3304 -0.1301 -0.1324 -1.4030 -1.0985 -0.0928 -0.1336 -0.4800 -0.9179 -1.1600 -0.6968 -1.4860 -0.7684
2020-11-16 07:51:35 | INFO | fairseq_cli.generate | NOTE: hypothesis and token scores are output in base 2
2020-11-16 07:51:35 | INFO | fairseq_cli.generate | Translated 4 sentences (43 tokens) in 384.7s (0.01 sentences/s, 0.11 tokens/s)

 

以上是我们在仅使用 CPU 的机器上运行 m2m_100 需要采取的所有步骤。 在没有 GPU 帮助的情况下,使用如此大的模型进行翻译肯定会非常缓慢,但这将帮助许多想要在将资金投入高性能 GPU 环境之前先在他们的任务中尝试或验证模型的人。

 

原文地址:https://twilightdema-14017.medium.com/running-fairseq-m2m-100-machine-translation-model-in-cpu-only-environment-27ca4da39a1e

最后编辑:
作者:sunny5156
喜欢技术....

留下一个回复