bert-as-service 日本語テキストのベクトル化サーバー構築

感情分析、テキスト分類など、多くのNLPアプリケーションで必要な処理として「テキストのエンコード/埋め込み」があります。

とある案件で約100万件/日のメールのテキスト分類タスクがあり、「テキストのエンコード/埋め込み」=「メール本文の固定長ベクトル化」をするため手法調査とサービス運用を視野にいれた環境構築をためしました。

 

おおよそ求めているのはこの辺りを満たすもの☟

・公開されている学習済みモデルを利用できる。
将来の運用にてモデルのfine-tuningは想定。初期ではモデルをゼロからトレーニングすることはしません。

・メール本文というそれなりに長い文章&複数文で構成されるテキストに対応する。
単語レベルの埋め込み表現でなく、文章コンテキストを表現します。

・実際の運用にはベクトル化後に分類タスクが控えており、ベクトル化自体高速な処理で終えたい。

 

幾つか調査した中で、2018年末に登場し様々な言語処理タスクで様々なSOTAを更新したNLPモデルBERTをエンコーダーとしてサービス化できる「bert-as-service 」の構築をしてみます。

bert-as-service 構築準備

bert-as-service 」ではBERTをセンテンスエンコーダーとして使用してサービスとしてホストします。

以下のような機能を持っています。

・事前トレーニング済みの12/24レイヤーのBERTモデルを利用して構築される。(独自の学習済みモデルでも運用可能です。

・少量のコードでテキストを固定長のベクトルとして取得が可能。

・低遅延、高速処理に最適化されている。Tesla M40 24GBで900文/秒。

・複数のクライアント、複数GPUでスケールの拡張ができる。

 

インストール

(今回の環境)

OS Ubuntu 18.04
GPU GeForce GTX 1070
Python 3.6
Tensorflow 1.14.0

 

pipで簡単にインストールできます。

$ pip install -U bert-serving-server bert-serving-client

 

公開されている学習済みモデルを配置

次に学習済みモデルを適当な位置に保存しておきましょう。

今回はGoogleが公開しているモデルをダウンロードし、zipファイルを models ディレクトリにダウンロード&解凍をします。

Google AIがリリースした事前トレーニング済みBERTモデルのリスト:

 

今回は多言語対応版モデルの BERT-Base, Multilingual Cased (New, recommended)を利用します。

$ mkdir ./models
$ cd ./models
$ wget https://storage.googleapis.com/bert_models/2018_11_23/multi_cased_L-12_H-768_A-12.zip
$ unzip multi_cased_L-12_H-768_A-12.zip

./models/multi_cased_L-12_H-768_A-12/ 以下に学習済みBERTモデルデータが展開されます。

bert_config.json
bert_model.ckpt.data-00000-of-00001
bert_model.ckpt.index
bert_model.ckpt.meta
vocab.txt

 

追記)

Google公開以外のモデルとして「京都大学 大学院情報学研究科 知能情報学専攻 知能メディア講座 言語メディア分野 工学部電気電子工学科)黒川・川原研究室」で公開されている「BERT日本語Pretrainedモデル(tensorflow版)」での動作を確認しました。

サービスを起動

以下コマンドにて起動させます。 -model_dir オプションで学習済みモデルの位置ディレクトリを指定します。

$ bert-serving-start -model_dir ./models/multi_cased_L-12_H-768_A-12/

デフォルトではGPU処理仕様で起動し、なければCPUバージョンの起動がされます。

オプションのひとつとして -num_worker=[NUMBER_OF_WORKER] にて同時処理ワーカーの数を指定可能です。-num_worker=4 なら最大4つのワーカーを同時に処理できます。

その他オプションは  bert-serving-start –help や公式にて確認しましょう。

 

#起動中のログいろいろ

usage: /usr/local/bin/bert-serving-start -model_dir ./model/multi_cased_L-12_H-768_A-12/
                 ARG   VALUE
__________________________________________________
           ckpt_name = bert_model.ckpt
         config_name = bert_config.json
                cors = *
                 cpu = False
          device_map = []
       do_lower_case = True
  fixed_embed_length = False
                fp16 = False
 gpu_memory_fraction = 0.5
       graph_tmp_dir = None
    http_max_connect = 10
           http_port = None
        mask_cls_sep = False
      max_batch_size = 256
         max_seq_len = 25
           model_dir = ./model/multi_cased_L-12_H-768_A-12/
    no_special_token = False
          num_worker = 1
       pooling_layer = [-2]
    pooling_strategy = REDUCE_MEAN
                port = 5555
            port_out = 5556
       prefetch_size = 10
 priority_batch_size = 16
show_tokens_to_client = False
     tuned_model_dir = None
             verbose = False
                 xla = False

:
#ログいろいろ
:

I1112 11:48:57.032177 140565767853824 __init__.py:164] all set, ready to serve request!

これでベクトル化の準備は完了です。

日本語テキストのベクトルの抽出

Pythonで記述するとこのような感じです。

from bert_serving.client import BertClient
bc = BertClient()

text_list = [ 'お世話になります。', 'はじめまして、' , '株式会社バートアズサービスの伊藤花子と申します。' ]

bc.encode(text_list)

# output 768次元にencodeされたベクトル
# [[-1.9442471   0.5215177   0.5582967  ...  0.05251018 -0.5523748  -0.0039347 ]
#  [-0.2243494   0.6562447   0.0960088 ...  1.7321543   0.23941146  -0.0011313]
#  [-1.2245594   0.39260447  0.26600635 ...  1.6061543   0.23941146  -0.08075813]]

テキストをリスト形式で渡し、それぞれテキストへの768次元にencodeされたベクトルが得られました。

これらをもとにして、文書分類やテキスト類似度の検索、ランキング学習等の別タスクへの特徴量として利用しましょう。

処理速度の計測

ここでは参考値として社内検証環境で速度計測を行いました。

CPUとGPUそれぞれの環境で、10,000件のテキストを入力としてベクトル化処理を複数回まわしてその平均値を比較。
CPUではCPUコア数=4から 起動時のオプション -num_worker=4 としました。

 
spec 処理時間 [sec] 時間当たり処理 [text/sec]
CPU Intel(R) Core(TM) i3-9100F CPU @ 3.60GH 166.5179022 60.05360305
GPU GeForce GTX 1070 12.46233234 802.4180165

 

CPU処理でもそれなりに速いので、実際の運用では「新規データの追加時などの適宜処理ではworker数の多いCPU」、「日毎などのバッチ処理で良いケースなら都度GPUインスタンス起動」と目的ごとにサーバー複数台で運用でしたほうがコスト的に良さそうな感じです。

まとめ

「bert-as-service」を構築し、自然言語処理の学習済みBERTモデルからテキストのベクトル化を簡単なステップで行えました。
一からの学習には多くの時間が必要なケースが多くモデルの肥大化も進むNLP分野において、公開されているPretrainedモデルや便利な運用環境など先人の肩に上手に乗りながらサービスへ導入検討をしていきたいですね。

最新ブログ一覧