takuti.me ABOUT

2014-01-25

TF-IDFで文書内の単語の重み付け

『いくつかの文書があったとき、それぞれの文書を特徴付ける単語はどれだろう?』こんなときに使われるのがTF-IDFという値。

TFはTerm Frequencyで、それぞれの単語の文書内での出現頻度を表します。たくさん出てくる単語ほど重要!

$\textrm{tf}(t,d)$
文書 $d$ 内のある単語 $t$ のTF値

$n_{t,d}$
ある単語 $t$ の文書 $d$ 内での出現回数

$\sum_{s \in d} n_{s,d}$
文書$d$内のすべての単語の出現回数の和

IDFはInverse Document Frequencyで、それぞれの単語がいくつの文書内で共通して使われているかを表します。いくつもの文書で横断的に使われている単語はそんなに重要じゃない!

$\textrm{idf}(t)$
ある単語 $t$ のIDF値

$N$
全文書数

$\textrm{df}(t)$
ある単語 $t$ が出現する文書の数

対数をとっているのは、文書数の規模に応じた値の変化を小さくするためなんだとか。

この2つの値を掛けたものをそれぞれの単語の重みにすれば、その値が大きいほど各文書を特徴付ける単語だと言えるんじゃないか、という話。

例えば10日分のアメリカ旅行の日記で全体を通して「アメリカ」という単語が多く登場していてもそれは当然のこと。1日目の日記を特徴づけるのは「飛行機」であって欲しいし、2日目は「ハンバーガー」であって欲しいわけです。

頻出する単語だからその文書を特徴付ける単語になる!とは限らない。そこでTF-IDFの登場。

具体例で見てみる

具体的な例として以下の記事を参考に、2つの文書『リンゴとレモンとレモン』(文書A)と『リンゴとミカン』(文書B)を考えます。

フツーって言うなぁ! Pythonでtf-idf法を実装してみた

形態素解析を行うとき、特徴語になり得るのは名詞だけだと仮定して、それ以外の品詞は無視します。つまり文書Aは [リンゴ, レモン, レモン] 、文書Bは [リンゴ, ミカン] という単語の集合。

$\textrm{tf}(\textrm{リンゴ}, \textrm{文書A}) = \frac{1}{3} = 0.33$

$\textrm{tf}(\textrm{レモン}, \textrm{文書A}) = \frac{2}{3} = 0.66$


 
$\textrm{tf}(\textrm{リンゴ}, \textrm{文書B}) = \frac{1}{2} = 0.5$

$\textrm{tf}(\textrm{ミカン}, \textrm{文書B}) = \frac{1}{2} = 0.5$

 
$\textrm{idf}(\textrm{リンゴ}) = \log{\frac{2}{2}} + 1 = 1$

$\textrm{idf}(\textrm{レモン}) = \log{\frac{2}{1}} + 1 = 1.3$

$\textrm{idf}(\textrm{ミカン}) = \log{\frac{2}{1}} + 1 = 1.3$

すると上記のようにTF値とIDF値がそれぞれ計算できて、積を求めれば、

$\textrm{tf}(\textrm{リンゴ}, \textrm{文書A}) * \textrm{idf}(\textrm{リンゴ}) = 0.33$
$\textrm{tf}(\textrm{レモン}, \textrm{文書A})*\textrm{idf}(\textrm{レモン}) = 0.858$

$\textrm{tf}(\textrm{リンゴ}, \textrm{文書B})*\textrm{idf}(\textrm{リンゴ}) = 0.5$
$\textrm{tf}(\textrm{ミカン}, \textrm{文書B})*\textrm{idf}(\textrm{ミカン}) = 0.65$

両方の文書に登場している「リンゴ」という単語は、片方にしか登場していない「レモン」や「ミカン」よりも特徴語としての重みは小さいことが数値的に分かります。

実装はRubyです。

tf_idf.rb

参考

徳永, "情報検索と言語処理", 東京大学出版会, pp. 27-28, 1999.