local llmでsentence embeddingどれ使えば良いんだっけ
最近の日本語喋れるLLMでそのままsentence embeddingしても良いんだっけ?そもそもどうやってsentence embeddingしてるんだっけ?と思っていたので調べてみた。
単語単位のembeding
実装はsentence tranfomerが参考になる。
sentence transfomerでない場合やbertのclsトークンを持たない場合は、単語embeddingを足し合わせて、単語列の長さで平均をとるmean_poolingがよく使われる手法らしい。
追加でattentionのweightも加味すると良いみたい。
sentence transfomerではpoolingする層を最後に追加して、出力がembeddingされたvectorになる。
Flan-T5
単語単位のembeddingしかできないが、mean_poolingを用いた場合が精度が良いらしい。
embedding vectorを使って文章のネガポジ判定がそこそこ良いみたい
https://blog.shikoan.com/t5-sentence-embedding/
文章単位のembedding
multilingualのものだと日本語にも対応している。
https://www.sbert.net/docs/pretrained_models.html
embeddingするだけなので軽量。これを使うのもあり
新しいのは最近出てないイメージ、日本語喋れる最近のLLMのほうが良さそうな気がしている
embeddingの評価
日本語喋れるLLMとsentence transfomerを比較してみる。
文章の類似度評価の方法としてSTS ベンチマークがあるhttps://github.com/PhilipMay/stsb-multi-mt
参考リンク: https://tech.yellowback.net/posts/sentence-transformers-japanese-models
日本語のデータセットはあるが、trainのデータセットで翻訳が原因で使えなくなっているので、直接ダウンロードしてくる。
!wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-ja-dev.csv
#!wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-ja-train.csv
!wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-ja-test.csv
!wget https://github.com/PhilipMay/stsb-multi-mt/raw/main/data/stsb-en-test.csv
データセットの中身には以下のように文章のセットと類似度スコアが入ってる
幼い子供が馬に乗っています。子供が馬に乗っています。4.75
ネズミを蛇に食べさせている男性がいます。男は蛇にネズミを食べさせている。5.0
女性がギターを弾いています。男がギターを弾いている。2.4
https://github.com/PhilipMay/stsb-multi-mt/blob/main/data/stsb-ja-dev.csv
評価の実行には、参考リンクのコードをそのまま使わせて頂く。
以下で実行
model='rinna/japanese-gpt-neox-3.6b-instruction-sft'
python evaluation_stsbenchmark_ja.py $model
結果は、「データセットの文章セットをembeddingした結果同士のコサイン類似度」と「データセットの類似度スコア」のスピアマンの順位相関係数となる。
参考リンクの日本語対応のsentence transfomerのうち、スコアの良さそうな結果のものは以下のようになっている。
model spearman_cos
distiluse-base-multilingual-cased-v2 72.3
paraphrase-multilingual-mpnet-base-v2 79.3
結果
色々なモデルで試してみる。
まずは日本語喋れるモデル
| model | spearman_cos |
|-------|-------------:|
| rinna/japanese-gpt-neox-3.6b-instruction-sft | 48.7 |
| cyberagent/open-calm-3b | 47.2 |
スコアは低め。(mean pooling使っているがpooling方法を変えれば上がる?)
日本語対応のsentence embeddingをいくつか試す
| model | spearman_cos |
|-------|-------------:|
| google/flan-t5-xl | -2.7 |
| sonoisa/t5-base-japanese-v1.1 | 38.3 |
| sonoisa/sentence-t5-base-ja-mean-tokens | 79.5 |
| sonoisa/sentence-bert-base-ja-mean-tokens-v2 | 80.0 |
| sonoisa/sentence-luke-japanese-base-lite | 81.3 |
bert baseのスコアが高い
rinnaと同じくらいのサイズのFlan-T5-XL(3B)も試してみたが、さすがに日本語喋れないのでだめ
所感
sentence transfomerだとembeddingだけなので軽いし早い。
rinnaとかcalmだと全体ロードなのでやっぱ遅い。
sentence-luke-japanese-base-liteはroberta baseなのでbertより少し性能が良いのかな?lukeとbertはデータセットは同じものを使って学習しているそう。
日本語だとt5のほうが性能が上のイメージあったけどbert baseのほうがスコアは高い(学習させたデータや学習済モデルにもよると思いますが)
日本語の会話ができるのとsentence embeddingできるのだと能力違うんだな、と