【自然言語処理100本ノック 2020】99. 翻訳サーバの構築【解答】【世界最速公開】【全米号泣】


概要

 物工/計数 Advent Calendar 2020、4コマ漫画に挟まれた12月24日(クリスマスイブ!)の記事です。

 自然言語処理の問題集「自然言語処理100本ノック 2020 第10章: 機械翻訳」の問99を解き、深層学習モデルによる翻訳のデモシステムを実装します。98までをやっていなくても英仏翻訳が実装できます。多分世界最速公開です。

イントロ

 自然言語処理100本ノック 2020 は正規表現といった基礎から近年の深層学習のトレンドに至るまで、自然言語処理のスキルを楽しく[要出典]身に付けることができる問題集です。

 解く上でMeCabに始まり様々なライブラリを使う必要があり、その環境構築をまともにやるのは非常に面倒なので、!pipで簡単に環境を作れるGoogle Colabを利用する人も多いはずです。僕もその一人です。ただし、最後の問991で大きな問題に直面することになります。

99. 翻訳サーバの構築
 ユーザが翻訳したい文を入力すると,その翻訳結果がウェブブラウザ上で表示されるデモシステムを構築せよ.

 んなことcolabでできるか!

と、思うじゃないですか。

 実は、できます!!!!!!!!!!

 そう、できます。恒久的なサーバを立てることはできませんが、デモシステムを作るだけならGoogle Colabで完結します。ということで、やっていきたいと思います。

 以下ではpytorchを使い、モデルを読み込んだ状態でスタートします。とりあえずやってみたい、という人は、fairseqを使い、公式のチュートリアルにあるように、

!curl https://dl.fbaipublicfiles.com/fairseq/models/wmt14.v2.en-fr.fconv-py.tar.bz2 | tar xvjf -

で訓練済みの英仏翻訳モデルを落とします。

 これを

!pip install fairseq

from fairseq.models.transformer import TransformerModel

model = TransformerModel.from_pretrained("wmt14.en-fr.fconv-py", "model.pt", "wmt14.en-fr.fconv-py")
model.eval()

とすればmodelには推論モードの英仏翻訳の訓練済みモデルが入っていることになります。そんな感じで、modelには訓練済みモデルを読み込んでおいてください。

いざ、ラスボス討伐!

 flaskというフォルダを作って以下ではそこにいることにします。(!cd (移動したいフォルダ)で移動できます。)

 まず、flask-ngrokライブラリをインストールします。flaskはPythonで簡単なウェブアプリを作れるもので、ngrokはローカルのサーバー上のサイトを安全に全世界に公開できるものです。これらを使うと、自分のトレーニングした翻訳モデルを使った翻訳サイトを公開することができます。(ただし、colab上で走らせている時間だけ。)

!pip install flask-ngrok

from flask_ngrok import run_with_ngrok
from flask import Flask, render_template, request

 必要なものを適宜読み込みます。

 templatesというフォルダをflaskの中に作り、さらにtemplatesの中に以下が書かれたファイルindex.htmlを作ります。

index.html
<html>
<body>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
    <form action="/" method="POST" enctype="multipart/form-data">
        <div>
            <label for="name">Text:</label>
            <input type="text" id="name" name="name" placeholder=" ">   
        </div>
        <div>
            <input type="submit" value="translate">
        </div>
    </form>
</body>
</html>

 フォルダとファイルの関係は、以下のようになっています。

flask/   <- 今いるところ
|--templates/
  |--index.html

 もう少しちゃんと書けば、もっとちゃんとしたデモシステムができますが、今回は最も簡単なものにします。

 さて、最後に以下をcolabで実行します。

app = Flask(__name__,template_folder="(前略)/templates")
run_with_ngrok(app)

@app.route("/", methods=["GET"])
def get():
    return render_template("index.html", \
        title = "En-Fr Translation (input)", \
        message = "Please enter the text you want to translate here.")

@app.route("/", methods=["POST"])
def post():
    text = request.form["name"]
    return render_template("index.html", \
        title = "En-Fr Translation (output)", \
"""
【翻訳パート開始】
"""
        output = model.translate(text, beam=5)
"""
【翻訳パート終了】
"""
        message = text+"       → "+output)

app.run()

 日本語の場合は入力をトークナイズしたりする必要があるので、構築したモデルによって異なりますが、もう少し手間がかかるはずです。ただ、翻訳パートは普通にpythonを書いて良いので、大した負担にはならないでしょう。

 出てきたurlをクリックすると、こんな感じで表示されます。

これにて自然言語処理100本ノックは終了です。メリークリスマス!

参考文献

・fairseqで自分でトレーニングしたTransformerモデルをロードする
 https://qiita.com/maechanneler/items/fc3ef22d5b89396ddbcd
・Flask on Google Colab
 https://medium.com/@kshitijvijay271199/flask-on-google-colab-f6525986797b
・【Flask】formからサーバーサイドにテキストや各種コントロール、ファイルを渡す
 https://tanuhack.com/flask-client2server/
・flaskのパスを指定する
 https://qiita.com/mink0212/items/a4eb875f19b0e47718d3


  1. 0-basedなので。