tf-idfについて

これは、ISer Advent Calendar 2020 14日目の記事として書かれました。

はじめに

tf-idfについて知っていますか?

知っています?では、おそらくこの記事の情報量は0です。 advent calendar8日目の記事を見て、休憩してください。 また、英語を読むのに抵抗がない人は、wikipediaのtf-idfにいろいろ書いてあって、ここに書いてあるより詳しいので読んでみてください。

tf-idfとは

tf-idfは、文章の集合に対して、ある文章の単語の重要度を数値化する際の1つの方法です。

tfは単語の出現頻度(term flequecy)、idfは単語の逆文章頻度(Inverse Document Frequency) です。 これの二つの掛け算をtf-idfすることで、ある文章中の出現する単語の重要度を評価できます。この数値を使うことで、検索等に用いることができます。

より詳細に

定義

使う記号を定めます。

 D = \{ d_1, \cdots d_n \} = \text{文章の集合}

 d_i = i番目の文章

 W = \{w_1, w_2, \cdots w_n \} = \text{D中に出現する単語集合}

 |d_{i}| = d_i における単語数

 |w_{i}|_j = 文章d_j における単語w_iの出現回数

その他集合にバーを付けたら、要素の数とします。

TFについて

まずは、素朴なTFです。この値は、文章 d_iと単語 w_jを引数に受け取ります。


tf(d_i, w_j) = \displaystyle \frac{|w_j|_i}{|W|}

ざっくりというと、 D全体で、ある単語がどれぐらい d_iに表れているかという数値になり、term flequencyになります。

IDFについて

以下のように定義できます。単語 w_iに対して定まります。


idf(w_i) = \log  \displaystyle \frac{|D|}{|\{d_i | w_i\in d_i\}| }

TFだけで、単語の重要性が図れそうに思いますが、よく出てくる単語(例:「まず」)の価値は低いと考えられ、めったに出てこない単語(例:「逆文章頻度」)は価値が高い単語と考えられます。よって、以上のIDFが必要になります。

また、単語によっては分母が0になったりするので、分母分子に1を足したりしている定義もあります。

tf-idf

tfとidfをかけるだけです。


tf\text{-}idf(d_i, w_i) = tf(d_i, w_i) \times idf(w_i)

そのほかの定義

頑張って書こうか悩んだんですが、疲れているので止めました。 日本語では、yukinoiさんのブログにいろいろ並んでいました。

英語の記事は豊富でした。

tf-idfを使ってできること

cos類似度

文章間での類似度を計算することができます。これは、単語1つ1つを1次元と見て、tf\text{-}idf(d_i, w_i)を文章 d_iの単語 w_I方向の大きさとした時の、文章ベクトルの内積 (\vec{d_i}, \vec{d_j})から定義することができます。

すなわち、以下のように定義できます。


cos(\vec{d_i}, \vec{d_j}) = \displaystyle \frac{(\vec{d_i}, \vec{d_j})}{||\vec{d_i}|| * ||\vec{d_j}||}

検索機能

他には簡単な検索機能を実装することができます。おそらく手順としては以下のようになります。

前準備

  1. 文章集合を用意する。この文章1つが検索の対象です。
  2. 必要であれば、文章中の単語を整形しておく。(半角カナを全角カナに変換する等)
  3. 文章それぞれを形態素解析し、単語に分割する。日本語であれば、これは、MeCabを使えばできます。書店でいろいろ見ましたが、pythonからどうやら使えるみたいです。
    インストールの際には、文字コードに気を付ける必要があります。コマンドプロンプトのデフォルトはshift_jisです。pythonから使う場合はutf-8がいいと思います。
  4. 文章の単語ごとにtf-idfを計算し、保存しておく。

検索の段階

  1. 検索のキーワードを形態素解析する
  2. ある文章における、キーワードの単語それぞれのtf-idfを使い、文章それぞれのスコアを計算する。
    単純に加算するなら以下のようになります。
     score(d_i) = \displaystyle \sum_{w\in d_i}tf\text{-}idf(d_i, w)
  3. 文章のスコアをソートし、検索結果として出す。

他には、cos類似度を使い、検索のスコアを最後にいじるともう少し精度がよくなるかもしれません。

さいごに

hatenaブログでのtex打ちはだるかった。