用語「tf-idf」について説明。各文書中に含まれる各単語が「その文書内でどれくらい重要か」を表す尺度で、具体的には「(ある文書における、ある単語の出現頻度)×(ある単語の文書間でのレア度)」などの計算値のこと。主に文書検索やレコメンデーションに使われている。
自然言語処理/機械学習におけるtf-idfとは、各文書(document)中に含まれる各単語(term)が「その文書内でどれくらい重要か」を表す統計的尺度の一つで、具体的には「ある文書内」で「ある単語」が「どれくらい多い頻度で出現するか」を表すtf(term frequency:単語頻度)値と、「全文書中」で「ある単語を含む文書」が「(逆に)どれくらい少ない頻度で存在するか」を表すidf(inverse document frequency:逆文書頻度)値を掛け合わせた値のことである(図1)。
1つのtf-idf値の計算を数式的に表現すると、要するに、
tf-idf値=(ある文書における、ある単語の出現頻度)
×(ある単語の文書間でのレア度)
を算出したものだ(より詳しい数式や、その計算内容や意味は後述する)。
この計算を複数の文書間の全単語に対して行うことで、各文章を構成する単語群を数値群によるベクトルに置き換えることができる(vectorize:ベクトル化)。文書ごとのベクトルは「各文書の特徴」を表現している(feature vector:特徴ベクトル)。2つの特徴ベクトルの類似度をコサイン類似度などを使って算出すれば、2つの文書の類似性が計測できる。
tf-idfは、主にこのような「文書の類似性を測る」などの目的で「文書のベクトル化」のために使われており、類似文書の検索などの情報検索や、「この記事に関連する記事のピックアップ」のようなレコメンデーションなどで広く活用されている。
より直観的に理解できるように、冗長にはなるが、シンプルな具体例を使って説明しておこう。例えば(文書というよりも単語の羅列ではあるが)、
という3つの文書があった場合を考えてみる。
まず、「イヌ」という単語は全文書にあるので(文書間でのレア度)は低い、つまり「レアではない=どの文書にもある」ということだ。このような単語は、文書を特徴付ける役割は弱いので、文書にとって「あまり重要ではない」と言えるだろう。よってtf-idf値もあまり高くならない。
次に、「ネコ」という単語は文書Bにしかないので(文書間でのレア度)は高い、つまり「レアである=限られた文書にしかない」ということだ。このような単語は、文書を特徴付ける役割は強いので、文書にとって「比較的重要である」と言えるだろう。しかも、文書Bにはその「ネコ」が4単語中の2単語と、50%の割合で存在する。「レア度が高い」×「頻繁に出現する」ということなので、「ネコ」は文書Bにおいて非常に重要である。よってtf-idf値は非常に高くなる。
数式を見る前に、tf-idfの計算内容をイメージしやすいよう、さらに冗長にはなってしまうが、上記の文書内容でtf-idf(+類似度)を手計算をしてみよう。なお計算方法には何種類かあるが、ここで示すのは最もシンプルな方法である(数式は後述する)。
まず表1では、全文書に含まれる全ての単語を重複なく列に取り、各文書(A/B/C)を行に取り、各セルにその単語の出現回数を記載した。
\ | イヌ | キジ | キツネ | サル | タヌキ | ネコ |
---|---|---|---|---|---|---|
文書Aでの出現回数 | 3 | 1 | 0 | 1 | 0 | 0 |
文書Bでの出現回数 | 1 | 0 | 1 | 0 | 0 | 2 |
文書Cでの出現回数 | 1 | 0 | 1 | 0 | 1 | 0 |
表1 各文書における各単語の出現回数(BoW:Bag of Words) |
表1のデータを基にtf値を計算する。各文書(例:「文書A」)における「ある単語」(例:「イヌ」)の出現回数(例:3回)を、その文書に含まれる全ての単語の総数(例:「文書A」に含まれる単語数5個)で割ればよい。カッコ書きで示した例の場合、「文書A」には5つの単語が含まれているため、3(「イヌ」の出現回数)÷5(「文書A」の総単語数)=0.6となる。
同様にして全ての計算を行ったのが表2である。表2の「文書A」行の「イヌ」列を見ると、確かに0.60という数値が記載されている。
\ | イヌ | キジ | キツネ | サル | タヌキ | ネコ |
---|---|---|---|---|---|---|
文書Aでのtf値 | 0.60 | 0.20 | 0 | 0.20 | 0 | 0 |
文書Bでのtf値 | 0.25 | 0 | 0.25 | 0 | 0 | 0.50 |
文書Cでのtf値 | 0.33 | 0 | 0.33 | 0 | 0.33 | 0 |
表2 各文書における各単語の出現頻度(tf:term frequency) |
次にidf値を計算する。計算の前提として、「ある単語」が含まれる文書の数(例:「ネコ」を含むのは文書Bの1個)を表3にまとめた
\ | イヌ | キジ | キツネ | サル | タヌキ | ネコ |
---|---|---|---|---|---|---|
全文書(3個)中での文書の数 | 3 | 1 | 2 | 1 | 1 | 1 |
表3 各単語を含む文書の数 |
表3を基に、全文書の数(例:表2の行数である3行)を、「ある単語」が含まれる文書の数(例:「イヌ」を含むのは文書A/B/Cの3個)で割り、その計算値の自然対数(log)値を算出する。log(3÷3)=0となる。「キツネ」は2つの文書に含まれるのでlog(3÷2)=0.41となり、「ネコ」は1つの文書に含まれるのでlog(3÷1)=1.1となる。
同様にして全ての計算を行ったのが表4である。表4の「ネコ」列を見ると、確かに1.10という数値が記載されている。
\ | イヌ | キジ | キツネ | サル | タヌキ | ネコ |
---|---|---|---|---|---|---|
idf値 | 0 | 1.10 | 0.41 | 1.10 | 1.10 | 1.10 |
表4 各単語の文書間でのレア度(idf:inverse document frequency) |
最後に、tf値(表2)とidf値(表4)を掛け算すればよい。文書Aの「イヌ」は0.60×0=0となり、文書Bの「ネコ」は0.50×1.10=0.55となる。
同様にして全ての計算を行ったのが表5である。表5の「文書B」行の「ネコ」列を見ると、確かに0.55という数値が記載されている。
\ | イヌ | キジ | キツネ | サル | タヌキ | ネコ |
---|---|---|---|---|---|---|
文書Aでのtf-idf値 | 0 | 0.22 | 0 | 0.22 | 0 | 0 |
文書Bでのtf-idf値 | 0 | 0 | 0.10 | 0 | 0 | 0.55 |
文書Cでのtf-idf値 | 0 | 0 | 0.14 | 0 | 0.37 | 0 |
表5 各文書における各単語の重要度(tf-idf) |
以上でtf-idfの計算は完了だ。文書A/B/Cに対する3つの特徴ベクトル(ちなみに、このように大部分の要素が0のベクトルを「疎ベクトル」と呼ぶ)が作成されている(表5の3行)。この3つを表の行と列に取り、各行と各列で示す2つのベクトル同士のコサイン類似度の値を表の各セルに記載したのが表6である。
\ | 文書A | 文書B | 文書C |
---|---|---|---|
文書A | 1 | 0 | 0 |
文書B | 0 | 1 | 0.06 |
文書C | 0 | 0.06 | 1 |
表6 各文書の特徴ベクトル同士で計算したコサイン類似度の一覧表 |
例えば表6の「文書B」行を見ると、
となっている。
既に計算例を示したが、あらためて数式としてまとめておこう。
上の式にあるnは「複数文書に含まれる全ての単語の種類数」を、mは「全文書の数」を意味する。前掲の表5の例だと、n=6(特徴量となる6列の単語の種類数)、m=3(ベクトルとなる3行の全文書数)となる。
まず、上の式で使われているtf値を計算する数式は次の通りだ。
次に、idf値を計算する数式は次の通りだ。次の式にあるlogは自然対数(底e)を指す。
ただし、実際の実装では、何らかの理由で単語がどの文書にも含まれない場合、分母が0(ゼロ)になり、ゼロ除算の問題が発生する可能性がある。これを避けるために、次のように分母に+1を加えることがある。
以上がtf-idfの基本的な数式になる。ただし、tf-idfの数式にはさまざまなバリエーションがあり、ライブラリーなどによって異なる。例えばscikit-learnが採用する数式による計算結果と、本稿で説明した数式による計算結果は同じにはならないので注意してほしい。各ライブラリーが採用する数式は、各ライブラリーのAPIリファレンスやソースコードを参照してほしい。
主要ライブラリーでtf-idfは、次のクラス/関数で定義されている。ただし、前述の通りライブラリーによって実装されている計算式が違ったり、指定するオプションによって計算式が変わったりするので注意してほしい。機械学習ではscikit-learnの関数がよく使われているようなので、基本的にはそれに倣うとよいだろう。
2024年4月8日:記事タイトルから英語表記を削除しました。疎ベクトルについて追記しました。
2024年9月17日:tf値の計算例と数式が誤っていました。具体的には「全文書に含まれる全ての単語の数」としていましたが、「文書_{j番目}に含まれる全ての単語の数」の誤りでした。お詫びして訂正させていただきます。また、ゼロ除算の回避に対応するバージョンの数式を書き加えました。
Copyright© Digital Advantage Corp. All Rights Reserved.