2016年4月20日水曜日

文書の類似度

前回、tf-idfを使って、文書に含まれる語句の出現頻度から重み付けを行いました。これは、文書の特徴を抽出するためということでした。「風の又三郎」と「セロ弾きのゴーシュ」で名詞を抜き出し、tf-idfの値を導出しましたが、まあ、両者で違いがあることがわかったという程度で、両者が明示的に比較されたわけではありませんでした。両者の違いというのは、両者がどれだけ似ていないかということにもなります。そこで、両者の類似度を求めれば、明示的に比較したことになります。
類似度を計算するときによく用いられる指標は相関です。でも、テキスト処理の分野だと、コサイン類似度という指標の方がよく用いられます。で、コサイン類似度というのは、文書をベクトルで表しておいて、そのベクトルどうしの関係を表現します。以下の式で表されます。
cos(x, y) = x・y / |x||y| = {x / |x|}・{y / |y|}
x, yはそれぞれ、文書ベクトルx = (x_1, x_2, ..., x_n), y = (y_1, y_2, ..., y_n)を表します。ベクトルの要素は共にn個あります。で、前回まで求めてきたtf-idfの結果を、上式に代入します。文書ベクトルの要素は、各文書の単語に対するtf-idfの値です。
文書の類似度を、Rを使って実際に求めてみましょう。前回、「セロ弾きのゴーシュ」を読み込みました。そこまではできているとします。で、新たに「注文の多い料理店」を読み込みます。
> menu <- Aozora(url = "https://www.aozora.gr.jp/cards/000081/files/
43754_ruby_17594.zip")
> library(RMeCab)
> listTFIDF <- docMatrix("NORUBY", pos=c("名詞"), weight = "tf*idf*norm" )
> head(listTFIDF, 20)
              docs
terms          chumonno_oi_ryoriten2.txt kazeno_matasaburo2.txt serohikino_goshu2.txt
  HOUSE                      0.023302018            0.000000000           0.000000000
  RESTAURANT                 0.023302018            0.000000000           0.000000000
  WILDCAT                    0.023302018            0.000000000           0.000000000
  あいつ                     0.014287567            0.004440664           0.000000000
  あすこ                     0.023302018            0.000000000           0.000000000
  あたりまえ                 0.014287567            0.002220332           0.000000000
  あっち                     0.014287567            0.006660996           0.000000000
  あと                       0.009014451            0.023814849           0.021455069
  あなた                     0.018028902            0.001400873           0.006130020
  イギリス                   0.023302018            0.000000000           0.000000000
  いっしょ                   0.009014451            0.014008735           0.009195030
  いも                       0.023302018            0.000000000           0.000000000
  いらっしゃい               0.139812109            0.000000000           0.000000000
  うし                       0.027043354            0.030819216           0.003065010
  うち                       0.009014451            0.015409608           0.024520079
  オーバー                   0.023302018            0.000000000           0.000000000
  おなか                     0.023302018            0.000000000           0.000000000
  おまけ                     0.014287567            0.002220332           0.000000000
  お客                       0.069906055            0.000000000           0.000000000
  お見舞                     0.023302018            0.000000000           0.000000000
>
今回、docMatrixの引数weightをtf*idf*normとしています。normというのは正規化を意味していまして、各文書(列)の要素を2乗して合計すると1になります。これは、類似度を計算するとき、都合がよいです。先に示した類似度の式では|x|および|y|が1になるということですから、文書ベクトルの内積を求めれば済むことになります。
> v1 <- as.vector(listTFIDF[,1])
> v2 <- as.vector(listTFIDF[,2])
> v3 <- as.vector(listTFIDF[,3])
>
一列目を取り出してベクトルv1、二列目をv2、三列目をv3とします。そして、それぞれのベクトルの内積を取ります。Rでは、ベクトルの内積は %*% を使います。単なる * だけだと、要素毎のかけ算になることに注意します。
> s12 <- v1 %*% v2
> s12
          [,1]
[1,] 0.1672723
> s23 <- v2 %*% v3
> s23
          [,1]
[1,] 0.1438562
> s31 <- v3 %*% v1
> s31
          [,1]
[1,] 0.1510847
>
この結果からは、どの文書も同等程度に似ていないということのようです。

0 件のコメント:

コメントを投稿