📖

NLLB-200 3.3B で日本語翻訳するメモ(moe-54b もあるよ)

2023/03/26に公開
1

LLM で日本語扱いたいけど, ええ感じの日本語特化 LLM まだない...

  • 日本語を英語に翻訳して LLM
  • 英語の LLM ファインチューンデータセットを日本語訳してファインチューン

でどうか.

翻訳には FuguMT ありますが,

https://note.com/npaka/n/n5146d9a444b4

今回は NLLB-200 を使ってみます.

https://ai.facebook.com/blog/nllb-200-high-quality-machine-translation/ja/

NLLB

https://github.com/facebookresearch/fairseq/tree/nllb

fairseq の nllb branch になっていますので注意ください.

モデルのライセンスは CC-BY-NC 4.0 つまり商用利用はできないです.
(翻訳したものでファインチューンした LLM 作ったら, 元 LLM が商用利用可能だったらファインチューンした LLM 自体は商用利用 OK そうではるが... 要ライセンス確認)

MoE = Mixture of Experts です.

https://github.com/facebookresearch/fairseq/blob/main/examples/translation_moe/README.md

https://qiita.com/cvusk/items/c5f9622d7b87c36bf4f5

よくわらん... とりま NLLB-moe は全部入りの翻訳モデルってことじゃろかね.

NLLB MoE 54B は元 pth ファイルで 400 GB, (fp16 あたりにしたので?) huggingface に上がっているのでは 250 GB くらいあります.

とりあえずは 3.3B(17 GB) 使います.
(後のほうで 54B CPU 動作のメモもあります)

環境

  • CPU: Threadripper + 128 GB CPU mem
  • GPU: 3090(24GB)

3.3B のモデルサイズは 17 GB くらいですので, 3090 に収まります.
(実 GPU メモリは 14 GB くらいのようなので, RX6800 や Tesla T4 などの 16 GB GPU mem でも動くかも)

翻訳速度そんなに重要でなければ CPU で処理でもよいでしょう. ただ下の GPT-4 紹介文だと翻訳に数分かかります. GPU 使っても数十秒(powerlimit 3090 で 23 秒)はかかります.

入力の言語自動判定をやめるといくらか速くなるかもはしれません.

日本語

https://github.com/facebookresearch/flores/blob/main/flores200/README.md#languages-in-flores-200

日本語の language code は jpn_Jpan です. 英語は eng_Latn

とりま CPU で動かします!

from transformers import AutoModelForSeq2SeqLM, AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained("facebook/nllb-200-3.3B")
model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-200-3.3B")

article = "UN Chief says there is no military solution in Syria"
inputs = tokenizer(article, return_tensors="pt")

translated_tokens = model.generate(
    **inputs, forced_bos_token_id=tokenizer.lang_code_to_id["jpn_Jpan"], max_length=30
)
ret = tokenizer.batch_decode(translated_tokens, skip_special_tokens=True)[0]
print(ret)
シリアに軍事的解決はないと国連総長

Cool!

GPT-4 説明を翻訳してみます!

https://openai.com/research/gpt-4

We’ve created GPT-4, the latest milestone in OpenAI’s effort in scaling up deep learning. GPT-4 is a large multimodal model (accepting image and text inputs, emitting text outputs) that, while less capable than humans in many real-world scenarios, exhibits human-level performance on various professional and academic benchmarks. For example, it passes a simulated bar exam with a score around the top 10% of test takers; in contrast, GPT-3.5’s score was around the bottom 10%. We’ve spent 6 months iteratively aligning GPT-4 using lessons from our adversarial testing program as well as ChatGPT, resulting in our best-ever results (though far from perfect) on factuality, steerability, and refusing to go outside of guardrails.

OpenAIのディープラーニングを拡大する取り組みの最新マイルストーンであるGPT-4を作成しました.GPT-4は,多くの現実世界のシナリオで人
間よりも能力が低いが,さまざまな専門的および学術的ベンチマークで人間レベルのパフォーマンスを発揮する大規模なマルチモダルモデル (画像とテキストの入力を受け,テキストの出力) です.例えば,試験受験者の上位10%のスコアでシミュレートされたバー試験に合格します.対照的に,GPT-3.5のスコアは下位10%のスコアでした.我々は6ヶ月間,対抗テストプログラムやChatGPTのレッスンを用いてGPT-4を繰り返し調整し,事実性と制御性,そしてガードレールの外に出ることを拒否する上でこれまでで最も優れた結果 (完璧とは程遠いもの) を得ました.

はわわ... 良き良きっぽ!

ずんだもん構文ためします!

https://note.com/npaka/n/n4651ee6d3c51

 ずんだもんは東北に住む活発でかわいい女の子です。

    あなた「きみの名前は?」
    ずんだもん「ボクの名前はずんだもんなのだ。」

    あなた「今日の天気は?」
    ずんだもん「ボクは今日の天気は晴れだと思うのだ」

    あなた「今日は何時に起きたの?」
    ずんだもん「ボクは7時に起きたのだ」

    あなた「年齢は?」
    ずんだもん「ボクの年齢は秘密なのだ」

    あなた「朝ごはんは何食べたい?」
    ずんだもん「ボクはおにぎり食べたいのだ」

    あなた「昼ごはんは何食べたい?」
    ずんだもん「

"I'm a very active and beautiful girl living in the East". "What's your name?" "I'm supposed to be a pretty girl". "What time did you wake up today?" "I woke up at 7 am". "What's your age?" "I'm supposed to be a secret". "What do you want to eat in the morning?" "I'm supposed to be eating in the afternoon". "What do you want to eat in the afternoon?" "I'm supposed to eat in the morning".

ずんだもんが I'm になりました...
Chat 用途やキャラ設定付けしたい場合ですと, なんらかの prompt engineering が必要そうです!

MoE 54B

https://huggingface.co/facebook/nllb-moe-54b

weight が 250GB なので頑張れば CPU 256 GB マシンでオンメモリ or huggigfae accelerate or deepspeed あたりで動かせます.
(fairseq の repo, いろいろコードごちゃまぜなので, とりま nllb-moe pth ファイル使って翻訳だけ利用したいときどうすればいいのかまったくわからん...)

執筆時点(2023/03/25)では pip で入る transformers (ややこしい名前であるが, transformer 系の ML をぺろっと使えるようにするやつ. ただいろいろな ML モデルサポートしすぎてコードは肥大化していってつらっぽ) で動かそうとすると, nllb_moe key error などでエラーになります.

2023/03/31 時点の transformers git 版で nllb-moe 対応されたので, 動作すると思われます.

https://github.com/huggingface/transformers/issues/22461

そのうち pip で入る transformers のバージョンでも動くでしょう.

とりま 256 GB CPU mem な x299(Skylake-X) マシンで動かしました.

MiB Mem : 257433.3 total,   5389.2 free, 214775.1 used,  37269.0 buff/cache
MiB Swap:   2048.0 total,   1050.7 free,    997.3 used.  40392.7 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 450952 syoyo     20   0  212.6g 208.2g 157640 R 288.8  82.8   6:05.33 python

実メモリ消費は 210 GB くらいでした.

load model time(s) 435.39693665504456

250 GB くらいあるので, weight の pytorch 処理 + メモリへのロードだけで 7 分くらいと結構時間かかります...
(今回はそんなに性能のよくない PCI-gen3 NVMe 利用)

メモリに直接展開 + mmap できる形式とかにしたらもうちょっと効率化されるかもです.

example の "UN Chief says there is no military solution in Syria" を日本語にします!

国連事務総長は,シリアに軍事的解決はないと述べた.
run time(s) 5.595441102981567

お~

ずんだもん構文の英訳試します!

ずんだもんは東北に住む活発でかわいい女の子です. You "君の名は?" ずんだもん "ボクの名前ははずんだもんなのだ". You "今日の天気は?" ずん だもん "ボクは今日の天気は晴れだと思うのだ" You "今日は何時に起きたの?" ずんだもん "ボクは7時に起きたのだ" You "年齢は?" ずんだもん " ボクの年齢は秘密である" You "朝ごはんは何食べたい?" ずんだもん "ボクはおにぎり食べたいのだ" You "昼ごはん
run time(s) 35.11597681045532

ぐぬぬ... なんかうまくいきませんでした.
moe-54b は英語 -> 日本訳に使うか, (本来の用途である?) ファインチューン/distilled 用の元モデルとして使うのがいいかもです.

CPU mem 128 GB で動かす.

最近の民生 PC(Core-i9, Ryzen9)ですと, 32 GB x 4(DDR4(or DDR5))で 128 GB も普通になってきているかと思います.

https://akiba-pc.watch.impress.co.jp/docs/price/monthly_repo/1496872.html

2023/05 時点では DDR4 であれば 128 GB(32 GB x 2 x 2)が 3 万円ちょっとで調達できます.
(https://eetimes.itmedia.co.jp/ee/articles/2303/29/news057.html メモリ不況は 2023 年末くらいまで続くっぽいので, 2023 年の年末だと DDR5 でも 128 GB 3 万円くらいで調達できるかもしれません)

とりま bfloat16 で動きました!
最初は fp16 を試しましたが, fp16 だと, https://huggingface.co/transformers/v4.7.0/_modules/transformers/models/m2m_100/modeling_m2m_100.html M2M100Encoder などで, LayerNorm が fp16 対応していないエラーが出てうごきませんでした...
(特定のレイヤーだけ fp32 のままにするという手もあるが, 面倒なので諦めました)

bfloat16 の場合,

model = AutoModelForSeq2SeqLM.from_pretrained("facebook/nllb-moe-54b", torch_dtype=torch.bfloat16)

と, torch_dtype=torch.bfloat16 指定するだけです.

メモリ消費は 100 ~ 115 GB ほどでした.

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
1579808 syoyo     20   0  114.4g 110.9g 148408 R  98.3  88.2   8:04.41 python

model のロード(+ bf16 変換)は 572.8429079055786 secs と 10 分くらいでした.

翻訳処理は

article = """VEX uses the VEXcode framework, which enables users to start coding quickly and easily. VEXcode can be written in Blocks, Python, or C++.  A VSCode extension can be found in the marketplace to assist students with coding.
"""

の短めのでも 138.76013445854187 secs(Threadripper 1900X 8 cores) で 2 分ちょい.
さすがに時間かかりますね...

VEXは,ユーザーが迅速かつ簡単にコーディングを開始できるようにするVEXcodeフレームワークを使用している. VEXcodeはBlocks,Python,またはC++
で記述できる. VSCode拡張機能は,学生のコーディングを支援するためにマーケットプレイスで見つけることができる.

翻訳品質はさすがで, fp32 の結果(↓「かしこさ」 section 参照)とほぼ同じ.

処理速度については, ggml などにポートできると, ロードと実行が高速化されそうではあります.
(ggml 化できたら, たぶんロードは数十秒(mmap 使用), 翻訳 20 秒くらいでできそう)

save_pretrained() で bf16 形式の保存も試しましたが,
処理時間はいくらか減りましたが, 劇的というほどではありませんでした.

また, bf16 で保存した場合でも, from_pretrained では再度 bf16 指定が必要です.
(torch_dtype を指定しない場合, 内部では bf16 -> fp32(torch_dtype のデフォルト) に復元している模様)

CPU 実行で Batch 処理は遅いかも?

https://note.com/npaka/n/n36acd2122192

を参考に,

inputs = tokenizer(batch_sentences, padding=True, truncation=True, return_tensors="pt")

という感じでバッチで処理させると翻訳処理が速くなるかと思い, させてみましたが, 逆にちょっと遅い感じになった模様?
padding で最も長い入力文に tensor が resize されたためですかね.

かしこさ

openassistant データセットから

VEX uses the VEXcode framework, which enables users to start coding quickly and easily. VEXcode can be written in Blocks, Python, or C++.  A VSCode extension can be found in the marketplace to assist students with coding.

を翻訳してみます(元英語は LLM が生成したもので, 翻訳のテストに使うにはやや曖昧な文章な感はあるが)

distilled-1.3B

VEXは,ユーザが迅速かつ簡単にコーディングを開始できるようにする VEXcodeフレームワークを使用しています. VEXcodeは,ブロック, Python,または C++ で記述できます. プログラミングの学生を支援するために,VSCode拡張子はマーケットプレイスで見つけることができます.

3.3B

VEXは,ユーザが迅速かつ簡単にコーディングを開始できるようにするVEXcodeフレームワークを使用しています. VEXcodeは,ブロック, Python,または C++で記述できます. 学生のコーディングを支援するために,市場ではVSCode拡張子が見つかります.

3.3B でも, 機械翻訳感があり微妙なところやね.

MOE-54B

fp32 の結果(スクショ)

https://twitter.com/syoyo/status/1655301435645636608?s=20

VEXは,ユーザーが迅速かつ簡単にコーディングを開始できるようにするVEXcodeフレームワークを使用している. VEXcodeはBlocks,Python,またはC++
で記述できる. VSCode拡張機能は,学生のコーディングを支援するためにマーケットプレイスで見つけることができる.

(↑の bfloat16 の結果)

54b は bfloat16 でも翻訳品質さすがですね.

その他

moe-54b は variant として

https://huggingface.co/ArthurZ/nllb-moe-128

がありますが, repo にファイルが足りない(tokenizer.json など)です.
試しに作ったがもうメンテされていない repo っぽい感じです.

128 は翻訳で使える最大トークン数(~= 文字数)と思われます.

まとめ

3.3B であれば GPU で動作可能.
54B は 128 GB mem CPU で動作可能.
(もしくは 8bit 量子化して A100 80 GB, or 3090 x 4 は可能であろう)

翻訳精度は 3.3B は Google 翻訳などの機械翻訳程度であまり品質は高くない.
翻訳で LLM 用日本語データセットつくるなら 54B 一択です.

model 構成

Switch Transformer ベース.

https://github.com/facebookresearch/fairseq/blob/nllb/fairseq/modules/transformer_layer.py

fairseq/modules/transformer_layer.py が Model 構成とおもうが, 他のモデルと共有させているためか, コード構成がややこしい.

https://github.com/huggingface/transformers/blob/main/src/transformers/models/nllb_moe/modeling_nllb_moe.py

transformers の models/nllb_moe/modeling_nllb_moe.py のほうが理解しやすいでしょう.

データセット

https://github.com/facebookresearch/fairseq/blob/nllb/examples/nllb/data/README.md

dataset は以下で構成される.

  • Primary Dataset
    • public data(翻訳データ). download スクリプトあり. 日本語はない. 25 GB くらい
    • NLLB Seed : 日本語はない. 50 MB くらい.
  • (mined) BiText
  • Backtranslation(逆翻訳)

NLLB Seed: Wikimedia の翻訳をベース.

https://github.com/facebookresearch/flores/tree/main/nllb_seed

BiText : Web にある public 翻訳データセット.

https://github.com/facebookresearch/LASERhttps://github.com/facebookresearch/stopes で mining(web をクロール?)して翻訳ペアを収集?

というわけで日本語は bitext mining(LASER, stopes) と Backtranslation (他の翻訳ツールか, NLLB 自体を使って?)で考慮するっぽい?
(論文には詳細かかれておらず, データセットもいろいろツール多岐に渡っていて調べるのがめんどい)

bitext mining

CCMatrix https://github.com/facebookresearch/LASER/tree/main/tasks/CCMatrix を参考にして, stopes で収集.

ちなみに, NLLB ではないが, 日英翻訳ペアのデータセット構築と pretrained model.

https://www.otofu.org/papers/morishita22nlp.pdf
http://www.kecl.ntt.co.jp/icl/lirg/jparacrawl/

JParaCrawl のデータセットとそれを使っての学習モデルは商用利用はできないので, 手法を参考にして自前で crawl するのがよいでしょう.

Backtranslation

https://github.com/facebookresearch/fairseq/blob/nllb/examples/nllb/data/README.md#backtranslated-datasets

mined bitext で一度学習して, それに対して backtranslation でさらに bitext をふやして, さらに学習という感じでしょうか.

TODO

  • NLLB を, Alpaca などのファインチューン用データセットの日本語翻訳に利用して, 日本語 LLM を極める
  • maxtoken を自動推定して処理時間を改善する
  • NLLB のデータセット収集方法をしらべ, 日本語と英語, 日本語と中国語など, 日本語に特化させて学習させたい

Discussion

w7a7w7a7

記事に直接関係がないランダムな質問で申し訳ないですが質問させてください。
"その他"のところに"repo にファイルが足りない(tokenizer.json など)です."と書いてありますがtokenizer.jsonはtokenizer.pyなどがあれば簡単に生成できるものではないのですか?モデル作成者が公開しなければ手に入れられないものなのですか?
(私もあるLLMモデルのtokenizer.jsonを必要としているのですが、そのhugging faceには公開されていませんでしたので。)
(昨日からLLMを触っているので意味不明でしたらすみません。)