Published on

sentence transformersで日本語を扱えるモデルのまとめ

Author
株式会社イエローバックの機械学習エンジニアです

はじめに

Sentence Transformersを用いて文章の埋め込みベクトルを作成できます。

以下のように応用できます。

  • 文章埋め込みベクトル
  • Semantic Textual Similarity
  • クラスタリング
  • 言い換えの探索
  • 翻訳文章の探索
  • セマンティック(意味)検索
  • Retrieve & Re-Rank
  • 文章要約
  • 多言語の画像検索、クラスタリング、重複検出

SentenceTransformers では、事前学習モデルがいくつか公開されているのですが、今回はこの中から日本語が扱えるモデルをまとめてみました。

事前学習モデル

https://www.sbert.net/docs/pretrained_models.html に事前学習モデルが記載されています。このなかの多言語対応モデルで日本語が扱えそうです。

これらの多言語モデルは、知識蒸留を用いて単一言語を多言語の文章埋め込みベクトルを作成するという方法 https://arxiv.org/abs/2004.09813 で作成されています。

distiluse-base-multilingual-cased-v1

  • 日本語は対象外

distiluse-base-multilingual-cased-v2

  • 知識蒸留(Knowledge Distillation)を利用
  • Teacher: mUSE(Multilingual Universal Sentence Encoder)
  • Student: distilbert-base-multilingual
    • tokenizer: BertTokenizer と同一なので、日本語の性能は期待できなさそう

paraphrase-xlm-r-multilingual-v1

  • 知識蒸留を利用
  • Teacher: paraphrase-distilroberta-base-v1
  • Student: xlm-roberta-base
    • tokenizer: sentencepiece(multilingual)

stsb-xlm-r-multilingual

  • 知識蒸留を利用
  • Teacher: stsb-bert-base
  • Student: xlm-roberta-base
    • tokenizer: sentencepiece(multilingual)

quora-distilbert-multilingual

  • 知識蒸留を利用
  • Teacher: quora-distilbert-base
  • Student: distilbert-base-multilingual
    • tokenizer: BertTokenizer と同一なので、日本語の性能は期待できなさそう

paraphrase-multilingual-MiniLM-L12-v2

  • 知識蒸留を利用
  • Teacher: paraphrase-MiniLM-L12-v2
  • Student: microsoft/Multilingual-MiniLM-L12-H384
    • tokenizer: sentencepiece(multilingual)

paraphrase-multilingual-mpnet-base-v2

  • 知識蒸留を利用
  • Teacher: paraphrase-mpnet-base-v2
  • Student: xlm-roberta-base
    • tokenizer: sentencepiece(multilingual)

LaBSE

  • Google 開発の埋め込みモデル
  • Bert トークナイザ (日本語の tokenize はいまいちのはず)

その他

比較として以下のエンコーダでも確認します。

  • xlm-roberta-base(オリジナル:fine tuning なし)
  • Multilingual Universal Sentence Encoder(mUSE)
  • Multilingual Universal Sentence Encoder(mUSE) Large

モデル毎のパラメタ数など

モデルbasetokenizervocabslayersparams (million)
mUSEspiece
mUSE Largespiece
LaBSEwordpiece501,15312470
xlm-roberta-basexlm-rspiece250,00212278
quora-distilbert-multilingualdistilbertwordpiece119,5476134
distiluse-base-multilingual-cased-v2distilbertwordpiece119,5476134
paraphrase-multilingual-mpnet-base-v2xlm-rspiece250,00212278
paraphrase-xlm-r-multilingual-v1xlm-rspiece250,00212278
paraphrase-multilingual-MiniLM-L12-v2Mul MiniLM L12 H384spiece250,03712117
stsb-xlm-r-multilingualxlm-rspiece250,00212278
  • hidden_size = 768
  • attn heads = 12

実験

文章類似度の評価のための STS ベンチマークを用いて日本語対応のモデルを評価してみます。 STS ベンチマークは英語のみですが、機械翻訳(deepl)で日本語に変換したものが公開されていましたので、今回はこれを利用することにします。

環境

  • python: 3.8
  • CuDA: 11.1
  • pytorch: 1.8.1
  • transformers: 4.9.2
  • datasets: 1.11.0
  • sentence-transformers: 2.0.0

事前準備

多言語用 STS ベンチマークデータセット(stsb_multi_mt)は huggigface datasets として公開されています。ただ日本語だけ対象外となっています。 どうやら、github issue によると train データに deepl で翻訳すると空行になってしまう箇所があり、そのためエラーとなっているようです。 今回は test データのみを使用しますのでデータとしては問題ないのですが、読み込みの設定で日本語が除外されていますので、 ローカルにコピーして修正します。

$ mkdir stsb_multi_mt_ja
$ cd stsb_multi_mt_ja
$ wget https://raw.githubusercontent.com/huggingface/datasets/master/datasets/stsb_multi_mt/stsb_multi_mt.py
$ mv stsb_multi_mt.py stsb_multi_mt_ja.py
$ wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-en-test.csv
$ wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-ja-test.csv
$ cd ..

stsb_multi_mt_ja.py を修正します。

--- stsb_multi_mt.py    2021-09-01 00:02:39.680965506 +0900
+++ stsb_multi_mt_ja.py 2021-09-01 00:03:18.401330860 +0900
@@ -38,7 +38,7 @@

 _LICENSE = "custom license - see project page"

-_BASE_URL = "https://raw.githubusercontent.com/PhilipMay/stsb-multi-mt/main/data"
+_BASE_URL = "./"


 class StsbMultiMt(datasets.GeneratorBasedBuilder):
@@ -76,7 +76,11 @@
             description="This is the Italian STS benchmark data set.",
         ),
         # here seems to be an issue - see https://github.com/PhilipMay/stsb-multi-mt/issues/1
-        # datasets.BuilderConfig(name="ja", version=VERSION, description="This is the Japanese STS benchmark data set."),
+        datasets.BuilderConfig(
+            name="ja",
+            version=VERSION,
+            description="This is the Japanese STS benchmark data set."
+        ),
         datasets.BuilderConfig(
             name="nl",
             version=VERSION,

修正後、以下のようにしてデータセットを取り込めます。

from datasets import load_dataset

ds = load_dataset('stsb_multi_mt_ja', 'ja', split='test')

評価指標

オリジナル(英語版)と同じように sentence1, sentence2 のコサイン類似度と similarity score についてのスピアマンの順位相関係数を計算します。

evaluation_stsbenchmark_ja.py
from sentence_transformers import SentenceTransformer, LoggingHandler
from sentence_transformers.evaluation import EmbeddingSimilarityEvaluator, SimilarityFunction
from datasets import load_dataset
import logging
import sys
import torch
import os

#Limit torch to 4 threads
torch.set_num_threads(4)

#### Just some code to print debug information to stdout
logging.basicConfig(format='%(asctime)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=logging.INFO,
                    handlers=[LoggingHandler()])
#### /print debug information to stdout

if len(sys.argv) > 1:
    model_name = sys.argv[1]
else:
    model_name = 'sentence-transformers/stsb-xlm-r-multilingual'

ds = load_dataset('stsb_multi_mt_ja', 'ja', split='test')
#ds_en = load_dataset('stsb_multi_mt_ja', 'en', split='test')

sentences1 = ds['sentence1']
scores = [x/5.0 for x in ds['similarity_score']]
sentences2 = ds['sentence2']
#sentences2 = ds_en['sentence2']

print(sentences1[:3], sentences2[:3])

model = SentenceTransformer(model_name)
evaluator = EmbeddingSimilarityEvaluator(
    sentences1,
    sentences2,
    scores,
    main_similarity=SimilarityFunction.COSINE)
model.evaluate(evaluator)

コード全体は、https://github.com/yellowback/evaluation_stsbenchmark_ja に置いてます。

結果

結果(日本語-日本語)

結果は以下のようになりました。mUSE については別の方法で計算しました。

modelspearman_cos
mUSE71.3
mUSE Large72.9
LaBSE68.1
xlm-roberta-base43.4
[Sentence BERT model]
quora-distilbert-multilingual70.7
distiluse-base-multilingual-cased-v272.3
paraphrase-multilingual-mpnet-base-v279.3
paraphrase-xlm-r-multilingual-v177.1
paraphrase-multilingual-MiniLM-L12-v276.7
stsb-xlm-r-multilingual79.2

SentenceBERT のモデルのほうが総じて良い結果になりました。 distilbert ベースのものはおそらくトークナイザの影響で日本語についてはあまり良い結果とはなりませんでした。

結果(日本語-英語)

次に、日本語の embeddings と英語の embeddings の近さを確認するために、 sentence2 を翻訳前の英語文章として同様の実験をおこないました。

modelspearman_cos
mUSE68.9
mUSE Large70.4
LaBSE67.6
xlm-roberta-base17.3
[Sentence BERT model]
quora-distilbert-multilingual68.2
distiluse-base-multilingual-cased-v270.7
paraphrase-multilingual-mpnet-base-v277.5
paraphrase-xlm-r-multilingual-v174.3
paraphrase-multilingual-MiniLM-L12-v274.1
stsb-xlm-r-multilingual79.3

fine tuning していない xlm-roberta-base 以外は、想定通り日本語どうしのものと大差ない値となりました。

おわりに

Sentence Transformers の事前学習モデルを用いて、日本語の文章類似度の評価をしました。 スピアマンの順位相関係数が 8 割程度とそこそこの値となりました。