Zenn
📐

数式から疎ベクトルの理解を深める

2025/03/12に公開

こんにちは、システムゼウスの鈴木です。
今回は疎ベクトルの発展的な紹介として、疎ベクトル生成方法の一つであるTF-IDFについて、具体例を交えて紹介します。

別の記事内で、文字一致による検索と疎ベクトルによる検索を比較しました。その中で、数値計算によって最適な回答を高速に決定することができると紹介しました。

No 文章 a b c d e f g h i j k
1 f k f e c h f g g e h k c c c 0 0 4 0 2 3 2 2 0 0 2
2 a a f c a c f c k c a k a k f 5 0 4 0 0 3 0 0 0 0 3
3 c e i e j b h b b b e i h a c 1 4 2 0 3 0 0 2 2 1 0
4 a g c d g i c a g c d i k c k 2 0 4 2 0 0 3 0 2 0 2
5 b c a c b c a c a d c k k c d 3 2 6 2 0 0 0 0 0 0 2

数値計算の際に重要になる考え方は、1つの文章に対する対象単語の登場回数(単語頻度: Term Frequency)と、対象単語が登場する文章が全体にどれくらい登場するのか(逆文書頻度: Inverse Document Frequency)、という考え方です。

単語頻度(TF)

これは、”文書中に多数出現する単語は、その文書にとって重要な単語である”という考え方に基づいた値です。これによると、たとえばaが最も登場する文書はNo.2なので、aのTF値が最も高いのはNo.2です。
ただし、日本語でいう「てにをは」のように、意味がないのに文章中で多数出現することが予想される単語のスコアを高くしても意味がないです。また、そのような単語は多くの文書に出現する可能性が高いため、単純にTF値を元に検索を行うと必要な情報を絞り込むことができず、検索に用いるのは適当ではありません。
具体例として、"c j"を検索クエリとしたときのことを考えます。この時、TF値に基づいた検索を行うと、おそらくNo.5が最適な検索結果となるでしょう。しかし、cは全文書に登場し、なおかつ各文章におけるTF値も高いため、この場合のcは「てにをは」であるようです。

逆文書頻度(IDF)

この値は、その単語を含む文章が、文書全体でみてどのくらい一般的なのかを表し、まれな単語ほど高い値が得られます。言い換えると、IDF値が高い単語ほど文章の絞り込みに適しているということになります。
先ほど同様、cとjのIDF値を比較してみましょう。cは全文章に登場しているため、「cを含む文章」という絞り込みは意味がありません。一方、jはNo.3にしか登場しないため、文書全体で見たときjを含む文章の方がまれである、ということができます。

実際の計算式

TF-IDFの実際の計算式を紹介します。

TFの算出式は以下のとおりです。

TF(t,d)=ft,dtdft,d TF(t, d) = \dfrac{f_{t, d}}{\sum_{t' \in d}{f_{t',d}}}

tは単語、dは文書を意味し、f_{t, d}は対象の文書における単語tの出現回数を表しています。また、該当文書に含まれる単語総数を分母に用いています。
これにより、単語の出現を回数ではなく割合で算出できるため、ただ長い文書がヒットしやすくなるのをある程度回避することができるようになります。

IDFは、出現頻度が少ない単語ほどスコアを高くしたいので、出現頻度の逆数を対数変換した値を用います。

IDF(t, D) = \log{\dfrac{N}{|{d \in D : t \in d}|}}

文書集合D内の、単語tを含んだ文章dの数で文章の総数N = |D|を割った商の対数を用いてidfとしています。対数変換することで、文書頻度の差が極端に大きくなることを防ぎ、バランスのとれたスコアリングが可能になります。

最後に、この2値の積をとってTF-IDF値として利用します。

TF-IDF(t, d, D) = TF(t, d) * IDF(t, D)

計算してみる

これらを踏まえて、検索クエリが"a b"だった時の最適な回答はどれなのかを考えてみましょう。
上記の計算式に当てはめていきます。なお、文章に使用したアルファベットの総数は15で統一しています。

No.1 = TF_a * IDF_a + TF_b * IDF_b
= \dfrac{0}{15} * \log{\dfrac{5}{4}} + \dfrac{0}{15} * \log{\dfrac{5}{2}} = 0
No.2 = \dfrac{5}{15} * \log{\dfrac{5}{4}} + \dfrac{0}{15} * \log{\dfrac{5}{2}} \fallingdotseq 0.0744
No.3 = \dfrac{1}{15} * \log{\dfrac{5}{4}} + \dfrac{4}{15} * \log{\dfrac{5}{2}} \fallingdotseq 0.2592
No.4 = \dfrac{2}{15} * \log{\dfrac{5}{4}} + \dfrac{0}{15} * \log{\dfrac{5}{2}} \fallingdotseq 0.0298
No.5 = \dfrac{3}{15} * \log{\dfrac{5}{4}} + \dfrac{2}{15} * \log{\dfrac{5}{2}} \fallingdotseq 0.1668

このため、TF-IDFに基づく判定によると、No.3が最適な回答である、となります。

そのほかの疎ベクトル生成方法

疎ベクトルの生成方法について、他の方法も簡単に紹介します。

  • BM25: 長い文書には単語の出現回数が多くなることの影響の補正、単語頻度に対する飽和関数の導入によるスコアの上限の設定などを考慮したTF-IDFの改良版です。[1]
  • SPLADE: 少し密ベクトル要素を混ぜ込んで疎ベクトルを生成するようにしたものです。事前学習済みの言語モデルを準備し、入力文に登場する単語の類語を含めて疎ベクトル生成を行うことで、疎ベクトルの検索を強化することができるようになります。

  • 疎ベクトルを生成できる埋め込みモデル: Pineconeが疎ベクトル対応の埋め込みモデルを提供しているようです。ドキュメントによると、数学的な生成方法よりも精度が高いとのことですが、このモデルは日本語対応しているのかどうか不明です。モデル名にenglishとあるので対応していなさそうですが...

おわりに

TF-IDFについて、具体例を交えて紹介しました。疎ベクトルへの理解が深まる一助になれば幸いです。
また、ご意見・ご指摘等ございましたらコメントしていただけると幸いです。

脚注
  1. BM25について詳しく知りたい方はこちらの記事をご覧ください ↩︎

株式会社システムゼウス

Discussion

ログインするとコメントできます