M2M100 で英日翻訳するメモ(MIT ライセンスで商用利用可能! LLM への翻訳レイヤーとして期待)
機械翻訳は, FuguMT や NLLB がありますが,
NLLB-200 3.3B で日本語翻訳するメモ(moe-54b もあるよ)
FuguMT は
- 最新 huggingface transformers だと結果がおかしい
- 英語と日本語以外扱えないので, いろいろ前処理が必要(fugumt ライブラリではいくらか処理してくれるようであるが)
- 精度としては規模相当(NLLB 1B くらいと同等かしら)
NLLB は
- ライセンスが CC-BY-NC 4.0 であり商用利用できない
- 多言語対応で英日翻訳だけしたい場合はちょっとオーバースペック
- 3.3B の次が moe 54B しかなくて使い勝手が悪い
- moe 54B を 10B くらいでファインチューン or 再学習する手もあるかもはしれないが...
という問題があります.
Hugging face model をあさっていたら M2M100 をみつけました.
(ちなみに Helsinki Opus も見つかりますが, 試したところ日本語翻訳精度はだめだめだったので諦めた)
fairseq なので, NLLB の元になった?機械翻訳のようです.
NLLB とことなり, fairseq のライセンスがそのまま適用されるので pretrained model も MIT ライセンスで使えます!
M2M100 にかんする論文は 2020 年と古いですが, pretrained model はちょくちょくアップデートされているようです.
400M, 1.2B https://huggingface.co/facebook/m2m100_1.2B , 12B の pretrained model があります. 大きさは正義ということで, 12B を使います.
M2M100 12B
いくつか variant がありますが, こんかいは
を使います. 最後の 5 epoch の平均を取ったもののようです.
model サイズは 47 GB です(fp32).
とりあえずは CPU で動かします.
ロードでは 90 GB くらい, 実行時は 45 GB くらい CPU memory を使いました.
デフォだと 20 tokens しか生成されないので, max_new_tokens=512
にしています.
from transformers import M2M100ForConditionalGeneration, M2M100Tokenizer
#en_text = """
#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.
#"""
en_text = """A VSCode extension can be found in the marketplace to assist students with coding."""
model = M2M100ForConditionalGeneration.from_pretrained("facebook/m2m100-12B-avg-5-ckpt")
tokenizer = M2M100Tokenizer.from_pretrained("facebook/m2m100-12B-avg-5-ckpt")
tokenizer.src_lang = "en"
encoded_ja = tokenizer(en_text, return_tensors="pt")
generated_tokens = model.generate(**encoded_ja, forced_bos_token_id=tokenizer.get_lang_id("ja"), max_new_tokens=512)
ret = tokenizer.batch_decode(generated_tokens, skip_special_tokens=True)
print(ret)
'VEXは、ユーザーが簡単かつ迅速にコーディングを開始できるようにするVEXcodeフレームワークを使用しています。VEXcodeはブロック、Python、またはC++で書くことができます。'
'VSCode 拡張子は、学生がコーディングをサポートするために市場で見つけることができます。'
おー.
ただ長い文章そのままだと max_new_tokens
増やしてもうまくいきませんでした.
一文づつ整形して入力するのがよさそうです. また, 一文の長さもあまり長いのはダメかもしれません.
かしこさ
↑の翻訳では, "学生がコーディングを", となっているのでさすがに NLLB mode 54B には及ばすですかね.
(まあ元の英語もちょい曖昧なところもあるので, "学生が"が正当な対訳かは議論の余地があろう)
NLLB 3.3B よりはかしこいので, 規模相当という感じでしょうか.
2023 年 6 月時点では, 精度と使いやすさの点で, 英日翻訳(日英翻訳)は M2M100 がベストそうです!
CTranslate2 で効率化(とたぶん高速化)
pytorch CPU でもそこそこ普通に動きますが, GPU でより高速化したいときもあります.
ctranslate2 で m2m100(NLLB も!)対応してました.
ctranslate2 使えば pytorch より高速に動くでしょう!(たぶん)
が見つかりますが, の ct2 変換済みモデルは古いのか最新 ctranslate2 では読めなかったため, ctranslate2 用に変換が必要です.
AttributeError: 'Namespace' object has no attribute 'langtoks'
と出る場合,
fairseq==0.10.2
と古いバージョンを使いましょう.
(また, その場合 python 3.8 である必要があります https://github.com/facebookresearch/fairseq/issues/3535 )
transformers ベース
ただ, ctranslate2 側では最新 fairseq 対応する予定はないのと, sentencepiece の tokenizer 設定がめんどいので, transformers ライブラリベースでの変換と利用がよいでしょう.
$ ct2-transformers-converter --model facebook/m2m100_1.2B --output_dir m2m100_1.2B
メモリは普通に transformers
を動かすときと同じくらい消費するでしょう.
12B を変換する場合, 最低でも 96 GB CPU mem マシンがいるでしょう.
(↑にあるようにロードで 90 GB くらい消費する. )
変換自体は, モデルがダウンロードされていれば 12 B でも数分で終わります.
import ctranslate2
import transformers
ct2_model_path="/path/to/m2m100_1.2B"
translator = ctranslate2.Translator(ct2_model_path)
tokenizer = transformers.AutoTokenizer.from_pretrained("facebook/m2m100_1.2B")
tokenizer.src_lang = "en"
source = tokenizer.convert_ids_to_tokens(tokenizer.encode("Hello world!"))
target_prefix = [tokenizer.lang_code_to_token["ja"]]
results = translator.translate_batch([source], target_prefix=[target_prefix])
target = results[0].hypotheses[0][1:]
print(tokenizer.decode(tokenizer.convert_tokens_to_ids(target)))
これで, tokenizer は transfoermers AutoTokenizer 経由で sentencepiece のをぺろっとよろしくセットアップして, translation してくれます!
ct2 形式にモデル変換されているため, ロードと実行では, 消費メモリは概ね model サイズと同等です(12B なら 48 GB くらいあれば OK).
量子化
int8 で 12 GB くらい, fp16 で 22 GB くらいに model サイズを減らすことができます.
(22 GB ならギリ 3090 x 1 で動かせますね)
ためしに int8 量子化 と fp16 量子化で翻訳してみます.
A VSCode extension can be found in the marketplace to assist students with coding.
fp16 の結果.
VSCode 拡張子は、学生がコーディングをサポートするために市場で見つけることができます。
fp32 と同等になりました(この一文しか試していないけども...)
int8 の結果.
VSCodeの拡張子は、学生がコーディングを手助けするために市場で見つけることができます。
int8 でもいけそうでしょうか. 1.2B よりはかしこいです. int8 は 16 GB CPU mem サーバーや, ノート PC とかで翻訳させたいときにいいかも.
他にも int16 と int8_float16 もあるので, いくつか試してみてくださいネ.
CPU なら int8, GPU なら float16 がよさそうでしょうか.
llama.cpp(ggml)でうごかす?
llama.cpp(ggml) で M2M100 の model 構築したらいい感じに CPU で爆速で動くことでしょう.
1.2B であれば, 量子化してスマホでオンデバで動かすのもできるでしょう.
翻訳がうまくいかないケース
- ニュース見出しなど短文だったり省略が多いもの
- ArXiv 論文など, 専門用語が多いもの
ある程度はドメインに特化したファインチューンで対応できるとは思います...
TODO
- 翻訳できる文の長さがどこまでいけるか調査する
- 英語メインの Chat LLM(Falcon-40B instruct など)の前段と後段に M2M100 の翻訳を入れて, 日本語でチャットでいい感じにする.
- llama.cpp などで動かす
- 日英翻訳も試す
- FuguMT の翻訳データセットを参考にして https://staka.jp/wordpress/?p=413 , back translation なども行い 5B ~ 20B くらいの規模で翻訳モデルの自前学習する!
- ctranslate2 C++ API で利用して, Python フリーで動かす!
Discussion