テキストをベクトル化するときに用いる基本的な方法の一つであるtf-idfについてこれから数回の更新でまとめていこうと思います。
最初にこの記事では一般的な定義と、scikit-learn(TfidfVectorizer)で引数を特に指定しなかった場合に実行されるデフォルトの定義について紹介し、
今後の記事でそのバリエーションとして、オプションを変えるとどのような定義で計算できるのかを紹介していく予定です。
さて、一言にtf-idfといってもその定義には非常に多くのバリエーションがあります。
英語版のWikipediaを見ていただくとそれらが紹介されています。
参考: tf–idf – Wikipedia (English)
一方で日本語版(この記事執筆時点)のWikipediaではそのうちの1個が紹介されています。
一般的にはこれを指すことが多そうなので、この記事ではこれを一般的な定義と呼びましょう。
参考: tf-idf – Wikipedia (日本語)
早速一般的な定義について紹介していきます。
文書$d$のtf-idfは、コーパス中の単語数に等しい長さのベクトルです。
そのベクトル中の単語$t$に対応する成分$\text{tfidf}_{t,d}$は次のように単語の出現頻度(Term Frequency)と、逆文書頻度(Inverse Document Frequency)の積として計算されます。
$$
\text{tfidf}_{t,d} = \text{tf}_{t,d}\cdot \text{idf}_{t}
$$
単語の出現頻度の定義は次のようになります。
$$
\text{tf}_{t,d} = \frac{\text{文書d中の単語tの出現回数}}{\text{文書dの全ての単語の出現回数の和}}
$$
そして、逆文書頻度の定義は次のようになっています。
$$
\text{idf}_{t} = \log{\frac{\text{総文書数}}{\text{単語tを含む文書数}}}
$$
ある文書に登場する単語は、その文書に多く登場するほど、tfが高まり、コーパス全体で珍しいほどidfが高まって、結果的にtfidfが高くなるようになります。
さて、ここまでが一般的なtfidfの定義の話でした。
普段、文書をtfidfでベクトル化するときは、僕はsciki-learnのTfidfVectorizerを使うことが多いです。
そのため、重要なのはTfidfVectorizerでどのように実装されているのかです。
User Guide をみると、tf, idfそれぞれ一般的なものとは違う設計になっていることがわかります。
参考: 6.2.3. Text feature extraction
まず、一番大きな特徴として、TfidfVectorizer(デフォルト設定)でベクトル化した文書はベクトルの長さが1になるように正則化されます。
これは単純に、tfidfベクトルに変換した後に、結果のベクトルをそれ自体の長さで割って返す実装になっています。
次に、tf,idfの定義がそれぞれ一般的なものと違います。
tf は、単語の出現頻度ではなく、単純に出現回数になっています。
$$
\text{tf}_{t,d} = \text{文書d中の単語tの出現回数}
$$
そして、idfについては、$\log$の中の分数の分子と分母にそれぞれ$1$を足す平滑化処理が行われており、さらに、最後に$1$が足されています。
つまり、TfidfVectorizerのidfは次の式で計算されます。
$$
\text{idf}_{t} = \log{\frac{1+\text{総文書数}}{1+\text{単語tを含む文書数}}}+1
$$
これらの3つの特徴と、オプションを変えた場合の挙動について今後の記事で紹介していきたいと思います。
– ベクトルの正規化
– tfの定義の違い
– idfの定義の違い