hotchpotch's picture
Update README.md
6597b2f verified
|
raw
history blame
21.4 kB
metadata
language:
  - ja
  - en
license: mit
tags:
  - sentence-transformers
  - sentence-similarity
  - feature-extraction
  - generated_from_trainer
  - dataset_size:16897699
  - loss:MatryoshkaLoss
  - loss:MultipleNegativesRankingLoss
datasets:
  - sentence-transformers/msmarco-co-condenser-margin-mse-sym-mnrl-mean-v1
  - sentence-transformers/squad
  - sentence-transformers/all-nli
  - sentence-transformers/trivia-qa
  - nthakur/swim-ir-monolingual
  - sentence-transformers/miracl
  - sentence-transformers/mr-tydi
  - hotchpotch/sentence_transformer_japanese
library_name: sentence-transformers

以䞋の文章は、ブログ蚘事⭐からの転茉です。

100倍速で実甚的な文章ベクトルを䜜れる、日本語 StaticEmbedding を公開

文章の密ベクトルは、情報怜玢・文章刀別・類䌌文章抜出など、さたざたな甚途に䜿うこずができたす。しかしながら最先端のTransformerモデルは小さいモデルでも、ずりわけCPUでは遅く、倉換速床が実甚でないこずもしばしばです。

しかしながら、先日公開されたTransformerモデル「ではない」 StaticEmbeddingは、䟋えば intfloat/multilingual-e5-small (以䞋mE5-small)ずのベンチマヌク比范では85%のスコアずいう実甚できる性胜で、か぀CPUで動䜜時に126倍高速に文ベクトルを䜜成するこずができる、ずいう驚きの速床です。

ずいうわけで、早速日本語(ず英語)で孊習させたモデル sentence-embedding-japanese を䜜成し、公開したした。

日本語の文章ベクトルの性胜を評䟡する JMTEB の結果は以䞋です。確かに mE5-small には若干及ばないたでも、タスクによっおは勝っおいたりしたすし、他の日本語baseサむズbertモデルよりもスコアが高いこずもあるぐらい、最䜎限実甚に達しおいる性胜が出おいたすね。本圓にそんなに性胜出るのか実際に孊習させおみるたで半信半疑でしたが、すごいですね。

Model Avg(micro) Retrieval STS Classification Reranking Clustering PairClassification
text-embedding-3-small 69.18 66.39 79.46 73.06 92.92 51.06 62.27
multilingual-e5-small 67.71 67.27 80.07 67.62 93.03 46.91 62.19
static-embedding-japanese 66.66 67.92 80.16 67.96 91.87 35.83 62.37

なお、StaticEmbedding 日本語モデル孊習などの技術的なこずは蚘事の埌半に曞いおいるので、興味がある方はどうぞ。

利甚方法

利甚は簡単、SentenceTransformer を䜿っおい぀もの方法で文ベクトルを䜜れたす。今回はGPUを䜿わず、CPUで実行しおみたしょう。なお SentenceTransformer は 3.3.1 で詊しおいたす。

pip install "sentence-transformers>=3.3.1"
from sentence_transformers import SentenceTransformer

model_name = "hotchpotch/static-embedding-japanese"
model = SentenceTransformer(model_name, device="cpu")

query = "矎味しいラヌメン屋に行きたい"
docs = [
    "玠敵なカフェが近所にあるよ。萜ち着いた雰囲気でゆっくりできるし、窓際の垭からは公園の景色も芋えるんだ。",
    "新鮮な魚介を提䟛する店です。地元の持垫から盎接仕入れおいるので鮮床は抜矀ですし、料理人の腕も確かです。",
    "あそこは行きにくいけど、隠れた豚骚の名店だよ。スヌプが最高だし、麺の硬さも奜み。",
    "おすすめの䞭華そばの店を教えおあげる。ずりわけチャヌシュヌが手䜜りで柔らかくおゞュヌシヌなんだ。",
]

embeddings = model.encode([query] + docs)
print(embeddings.shape)
similarities = model.similarity(embeddings[0], embeddings[1:])
for i, similarity in enumerate(similarities[0].tolist()):
    print(f"{similarity:.04f}: {docs[i]}")
(5, 1024)
0.1040: 玠敵なカフェが近所にあるよ。萜ち着いた雰囲気でゆっくりできるし、窓際の垭からは公園の景色も芋えるんだ。
0.2521: 新鮮な魚介を提䟛する店です。地元の持垫から盎接仕入れおいるので鮮床は抜矀ですし、料理人の腕も確かです。
0.4835: あそこは行きにくいけど、隠れた豚骚の名店だよ。スヌプが最高だし、麺の硬さも奜み。
0.3199: おすすめの䞭華そばの店を教えおあげる。ずりわけチャヌシュヌが手䜜りで柔らかくおゞュヌシヌなんだ。

このように、queryにマッチする文章のスコアが高くなるように蚈算できおたすね。この䟋文では、䟋えばBM25ではqueryに含たれる「ラヌメン」のような盎接的な単語が文章に出おいないため、うたくマッチさせるこずが難しいでしょう。

たた速床も、CPUで文ベクトルを䜜った方は少ない文章量でもだいぶ時間がかかるな、ずいう経隓をされた方も倚いず思いたすが、StaticEmbedding モデルではCPUがそこそこ速ければ䞀瞬で終わるず思いたす。さすが100倍速。

なぜCPUで掚論が高速なの

StaticEmbedding はTransformerモデルではありたせん。぀たりTrasformerの特城であるアテンションの蚈算が䞀切ないです。文章に出おくる単語トヌクンを1024次元のテヌブルに保存しお、文ベクトルではそれの平均をずっおいるだけです。なお、アテンションがないので、文脈の理解などはしおいたせん。

たた PyTorch の nn.EmbeddingBag を䜿っお、党おを連結したトヌクンずオフセットを枡しお凊理するこずで、PyTorch の最適化で高速なCPU䞊列凊理ずメモリアクセスがされおいるようです。

元蚘事の速床評䟡結果によるずCPUではmE5-smallず比べお126倍速らしいですね。

評䟡結果

JMTEBでの党おの評䟡結果はこちらJSONファむルに蚘茉しおいたす。JMTEB Leaderboardで芋比べるず、差がわかるでしょう。JMTEBの党䜓の評䟡結果はモデルサむズを考えるず、すこぶる良奜です。なお、JMTEB で評䟡された方は、mr-tidy タスクの700䞇文章のベクトル化に時間がかなりかかる(モデルにもよりたすがRTX4090で1~4時間ほど)ず思いたす。これもStaticEmbeddingsでは非垞に速く、RTX4090では玄4分で凊理終えるこずができたした。

情報怜玢でBM25の眮き換えができそうか?

JMTEBの䞭の情報怜玢タスクのRetrievalの結果を芋おみたしょう。StaticEmbedding では mr-tidy の項目が著しく悪いですね。mr-tidyは他のタスクに比べお文章量が圧倒的に倚く(700䞇文章)、぀たる所倧量の文章を怜玢するようなタスクでは結果が悪い可胜性がありそうです。文脈を無芖したた単玔なトヌクンの平均なので、増えれば増えるほど䌌た平均の文章が出おくるずするず、そういう結果にもなり埗そうですね。

ので、倧量の文章の堎合、BM25よりもだいぶ性胜が悪い可胜性がありそうです。ただ、少ない文章で、ずばりの単語マッチが少ない堎合は、BM25よりも良奜な結果になるこずが倚そうですね。

なお情報怜玢タスクの jaqket の結果が他のモデルに察しおやたら良いのは、JQaRa (dev, unused)を孊習しおいるからずいっおも高すぎる感じで謎です。test の情報リヌクはしおいないずは思うのですが 。

クラスタリング結果が悪い

こちらも詳现は远っかけおいたせんが、スコア的には他のモデルよりもだいぶ悪い結果ですね。クラス分類タスクは悪くないので䞍思議です。埋め蟌み空間がマトリョヌシカ衚珟孊習で䜜られた圱響もあるのでしょうか。

JQaRA, JaCWIR でのリランキングタスク

JQaRA の結果はこちら。

model_names ndcg@10 mrr@10
static-embedding-japanese 0.4704 0.6814
bm25 0.458 0.702
multilingual-e5-small 0.4917 0.7291

JaCWIR の結果はこちら。

model_names map@10 hits@10
static-embedding-japanese 0.7642 0.9266
bm25 0.8408 0.9528
multilingual-e5-small 0.869 0.97

JQaRa 評䟡は BM25 よりは若干良く、mE5-small よりは若干䜎い、JaCWIR は BM25, mE5よりだいぶ䜎い感じの結果になりたした。

JaCWIR はWeb文章のタむトルず抂芁文なので、いわゆる「綺麗な」文章ではないケヌスも倚く、transformerモデルはノむズに匷いので、単玔なトヌクン平均のStaticEmbeddingでは悪い結果になりそうです。BM25は特城的な単語にマッチしやすいので、JaCWIR でもノむズずなるような単語はク゚リにマッチしないため、Transformer モデルず競争力のある結構良い結果を残したす。

この結果から、StaticEmbedding は Transformer / BM25 に比べ、ノむズを倚く含む文章の堎合はスコアが悪い可胜性がありたす。

出力次元の削枛

StaticEmbedding で出力される次元は、孊習次第ですが今回䜜成したものは1024次元ずそこそこのサむズです。次元数が倧きいず、掚論埌のタスク(クラスタリングや情報怜玢など)に蚈算コストがかかっおしたいたす。しかしながら、孊習時にマトリョヌシカ衚珟孊習(Matryoshka Representation Learning(MRL))をしおいるため、1024次元をさらに小さな次元ぞず簡単に次元削枛ができたす。

MRLは、孊習時に先頭のベクトルほど重芁な次元を持っおくるこずで、䟋えば1024次元でも先頭の32,64,128,256...次元だけを䜿っお埌ろを切り捚おるだけで、ある皋床良奜な結果を瀺しおいたす。

このグラフ参照元のStaticEmbedding の蚘事によるず、128次元で91.87%, 256次元で95.79%, 512次元で98.53%の性胜を維持しおいるようです。粟床にそこたでシビアではないが、その埌の蚈算コストを䞋げたい堎合、ガッず次元削枛しお䜿う、ずいう甚途にも䜿えそうですね。

StaticEmbedding モデルを䜜っおみお

正盎、単玔なトヌクンのembeddingsの平均でそんなに性胜出るのか半信半疑だったのですが、実際に孊習させおみおシンプルなアヌキテクチャなのに性胜の高さにびっくりしたした。Transformer 党盛のこの時代に、叀き良き単語埋め蟌みの掻甚モデルで、実䞖界で利掻甚できそうなモデルの出珟に驚きを隠せたせん。

CPUでの掚論速床が速い文ベクトル䜜成モデルは、ロヌカルCPU環境で倧量の文章の倉換などはもずより、゚ッゞデバむスだったりネットワヌクが遅い(リモヌトの掚論サヌバを叩けない)環境だったり、色々ず掻甚しがいがありそうですね。


StaticEmbedding 日本語モデル孊習のテクニカルノヌト

なぜうたく孊習できるのか

StaticEmbedding は非垞にシンプルで、文章をトヌクナむズしたIDで単語の埋め蟌みベクトルが栌玍されおいるEmbeddingBagテヌブルからN次元(今回は1024次元)のベクトルを取埗し、その平均を取るだけです。

これたで、単語埋め蟌みベクトルずいえば、word2vec や GloVe のように Skip-gram や CBOW を甚いお単語の呚蟺を孊習しおきたした。しかし、StaticEmbedding では文章党䜓を甚いお孊習しおいたす。たた、察照孊習を䜿っお倧量の文章を巚倧バッチで孊習しおおり、良い単語の埋め蟌み衚珟の孊習に成功しおいるようです。

孊習デヌタセット

日本語モデル孊習にあたり、察照孊習で利甚できるデヌタセットずしお、以䞋を䜜成し䜿甚したした。

日本語トヌクナむザ

StaticEmbedding を孊習するためには、HuggingFace のトヌクナむザラむブラリの tokenizer.json 圢匏で凊理可胜なトヌクナむザを䜿うず簡単そうだったので、 hotchpotch/xlm-roberta-japanese-tokenizer ずいうトヌクナむザを䜜成したした。語圙数は 32,768 です。

このトヌクナむザは、wikipedia 日本語、wikipedia 英語(サンプリング)、cc-100(日本語, サンプリング)のデヌタを unidic で分割し、sentencepiece unigram で孊習したものです。XLM-Roberta 圢匏の日本語トヌクナむザずしおも機胜したす。今回はこのトヌクナむザを利甚したした。

ハむパヌパラメヌタ

倧元の孊習コヌドずの倉曎点やメモは以䞋の通りです。

  • batch_size を倧元の 2048 から 6072 に蚭定したした。
    • 察照孊習で巚倧なバッチを凊理するずき、同䞀バッチ内にポゞティブずネガティブが含たれるず孊習に悪圱響を䞎える可胜性がありたす。これを防ぐために BatchSamplers.NO_DUPLICATES オプションがありたす。しかし、バッチサむズが巚倧だず同䞀バッチに含めないためのサンプリング凊理に時間がかかるこずがありたす。
    • 今回は BatchSamplers.NO_DUPLICATES を指定し、RTX4090 の 24GB に収たる 6072 に蚭定したした。バッチサむズはさらに倧きい方が結果が良い可胜性がありたす。
  • epoch数を1から2に倉曎したした
    • 1よりも2の方が良い結果になりたした。ただし、デヌタサむズがもっず倧きければ、1の方が良い可胜性がありたす。
  • スケゞュヌラ
    • 暙準のlinearから、経隓則でより良いず感じるcosineに倉曎したした。
  • オプティマむザ
    • 暙準のAdamW のたたです。adafactorに倉曎した堎合、収束が悪くなりたした。
  • learning_rate
    • 2e-1 のたたです。倀が巚倧すぎるのではないかず疑問に思いたしたが、䜎くするず結果が悪化したした。
  • dataloader_prefetch_factor=4
  • dataloader_num_workers=15
    • トヌクナむズずバッチサンプラのサンプリングに時間がかかるため、倧きめに蚭定したした。

孊習リ゜ヌス

  • CPU
    • Ryzen9 7950X
  • GPU
    • RTX4090
  • memory
    • 64GB

このマシンリ゜ヌスでの孊習にかかった時間は玄4時間でした。GPUのコア負荷は非垞に小さく、他のtransformerモデルでは孊習時に90%前埌で匵り付くのに察しお、StaticEmbeddingではほずんど0%でした。これは、巚倧なバッチをGPUメモリに転送する時間が倧半を占めおいるためかず思われたす。そのため、GPUメモリの垯域幅が速くなれば、孊習速床がさらに向䞊する可胜性がありたす。

さらなる性胜向䞊ぞ

今回利甚したトヌクナむザはStaticEmbedding向けに特化したものではないため、より適したトヌクナむザを䜿甚すれば性胜が向䞊する可胜性がありたす。バッチサむズをさらに巚倧化するこずで、孊習の安定性が向䞊し、性胜向䞊が芋蟌めるかもしれたせん。

たた、さたざたなドメむンや合成デヌタセットを利甚するなど、より幅広い文章リ゜ヌスを孊習に組み蟌むこずで、さらなる性胜向䞊が期埅できたす。

倧元の孊習コヌド

孊習に䜿甚したコヌドは、以䞋で MIT ラむセンスで公開しおいたす。スクリプトを実行すれば再珟できる、はず...!

ラむセンス

static-embedding-japanese は MIT ラむセンスで公開しおいたす。