はじめに
アヤさん、たんじょーび、おめでとう!! nikkieです。
みんなアイうた見ていて嬉しい限り♪
sentence-transformersというPythonのライブラリがあります。
こいつでembeddings(テキストの埋め込み表現)が計算できるらしく、気になったので触ってみました。
※レベル感としては使い出しレベル、やってみた系です。
目次
動作環境
pip install sentence-transformers
で入ったライブラリのうち主なもののバージョンはこちら
- torch 2.0.1
- transformers 4.30.2
- tokenizers 0.13.3
- huggingface-hub 0.16.4
- numpy 1.25.0
- scikit-learn 1.3.0
ドキュメントの例でembeddingsを計算(英語テキスト)
ドキュメントトップのUsageの例を写経していきます。
これは英語テキストのembeddingsを計算します。
https://www.sbert.net/#usage
- 指定しているモデルは all-MiniLM-L6-v2
- テキストを384次元のembeddingsに変換
- モデルサイズが非常に小さくダウンロードは一瞬でした
- 小さいので性能は高くないのかもしれません
- スクリプトの動作確認用途にぱっと使えそうなのが好感触
- 英語テキスト3文
- 1文目と2文目は近そうですよね(sentenceという共通語)
- 3文目は1文目・2文目と全然関係なさそうです
人が読んで感じる文同士の意味的な近さがembeddingsに表れているか、コサイン類似度を求めてみます。
>>> from sklearn.metrics.pairwise import cosine_similarity >>> cosine_similarity(embeddings[0].reshape(1, -1), embeddings[1].reshape(1, -1)) array([[0.53807926]], dtype=float32) >>> cosine_similarity(embeddings[0].reshape(1, -1), embeddings[2].reshape(1, -1)) array([[0.11805625]], dtype=float32)
2つのベクトルのコサイン類似度1は-1から1の値です。
1に近いほど2つのベクトルの向きが揃っている(=近い)ということですから、算出結果から
- 1文目と2文目は近い
- 1文目と3文目は遠い
と、人が読んだ時の感覚と一致すると言えそうな結果でした
日本語テキストからembeddingsを計算
英語について動かせたので、次は日本語の例を探します。
見つかったのがnpakaさん2のnote。
- 多言語を扱えるモデル stsb-xlm-r-multilingual
- 768次元のembeddings
- モデルサイズは大きく、1GBありました(ダウンロードにちょっとかかります。ダウンロード後に保存されるので一度だけです)
- sentense-transformersの中にコサイン類似度を計算する関数がある
- sentence_transformers.util.cos_sim
- npakaさんが使ったpytorch_cos_simは中でcos_simを呼ぶだけでした3
- これを使うためにencodeメソッドに
convert_to_tensor=True
を指定!
- sentence_transformers.util.cos_sim
cos_sim
の出力する類似度(scores
)のsizeは[1, 5]
- 768次元の1つのベクトル(
[1, 768]
)と5つのベクトル([5, 768]
)の類似度なのでこのsizeですね - 類似度最大の文を知りたいのでargmaxでインデックスを得ています
- 2つのベクトルと5つのベクトルになったら2つargmaxが返るようにdim=1と指定しています4
- 768次元の1つのベクトル(
文: 今日は雨降らなくてよかった 類似文: 今日は良いお天気ですね 類似度: tensor([[ 0.1204, -0.0705, 0.1849, 0.5848, 0.5198]])
文: ハンバーガーは好きですか? 類似文: 好きな食べ物は何ですか? 類似度: tensor([[ 0.5839, 0.0653, -0.0964, 0.1122, 0.0838]])
類似文は近いものが返せていますね!
一度モデルをダウンロードした状態でスクリプトをCPUで動かすと、1回の類似度計算に5-6秒かかりました。
終わりに
sentence-transformersライブラリを使って、テキストのembeddingsや類似度を計算しました。
英語や日本語用のモデルをダウンロードしてきて、ローカル環境で(=Web APIは呼び出さずに)embeddingsを計算できます。
Hugging Faceのtransformersライブラリのように、非常に簡単に動かせますね。
OpenAIのEmbeddings APIでもテキストからembeddingsを計算できますが、従量課金です。
embeddingsを保存するvector store関係の素振りのためにEmbeddings APIを毎回呼ぶというのは少し抵抗がありました(塵も積もれば山となりそう)。
そこで、費用をかけずにembeddingsを算出する方法(ローカル環境だけで完結する方法)を知りたく、sentence-transformersを触ってみました。
素振りにかかる費用はなるべく抑えて、精度を求める段階になったらぶっぱ(金の弾丸)というのが私の好むアプローチです。
- https://scikit-learn.org/stable/modules/metrics.html#cosine-similarity↩
-
LLM関係のnoteの数がすごいですし、書籍も出たばかりで、信頼できる情報源という認識です。
↩『OpenAI GPT-4/ChatGPT/LangChain 人工知能プログラミング実践入門』 が発売になります。|npaka @npaka123 #note https://t.co/bA94B3xGux
— 布留川英一 / Hidekazu Furukawa (@npaka123) 2023年6月2日 - エイリアスにすぎないようです。ref: https://github.com/UKPLab/sentence-transformers/blob/v2.2.2/sentence_transformers/util.py#L23-L28↩
-
torch.Tensor.argmax
のドキュメントから案内されるtorch.argmax
のドキュメントより↩