検索語・文書行列

参考文献

Rのパッケージ RMeCabの関数ファミリdocMatrix, docMatrix2, docMatrixDF は、検索語・文書行列(term-document matrix)を生成する。

検索語・文書行列(または、たんに文書行列)とは、ある(形態素原形としての)term(検索語)$t_j$ が文書ファイル $d_k$ 内に現れるterm頻度(TF: term frequency)を $tf_{ij}$ としたとき、指定したカテゴリの $m$ 語からなる全てのterm $t_j (j=1\dots m)$ と検索する $n$ 個からなる全ての文書ファイル $d_k (k=1\dots n)$ についてtermの頻度を求めた次のような$m$行-$n$列からなる行列 $F=(tf_{jk})$ として定義される。 \[ F= \begin{bmatrix} tf_{11} & tf_{12} & \ldots & tf_{1n}\\ tf_{21} & tf_{22} & \ldots & tf_{2n}\\ \vdots & \vdots & \ldots & \vdots\\ tf_{m1} & tf_{m2} & \ldots & tf_{mn} \end{bmatrix} \]

検索語・文書行列を使うと、文書間の類似性(あるいは差異)を検討することができる。 ある文書集合においてあるterm群(検索語集合)が高い頻度で登場している一方で、別の文書集合では同じターム群が低い頻度でしか現れないとすれば、それら2つの文書集合は語彙の使い方において別種の文書グループとして類別してもよいだろう。

検索語・文書行列の例

次は、小川未明の「赤い鳥」、岸田 国士の「飯田の町に寄す」および 種田山頭火の「歩々到着」の3つのテキスト本文(ルビなし)を kishida.txt, ogawa.txt, santouka.txt としてフォルダ text 内に置き、関数 docMatrix の引数として以下のように、フォルダ text (したがって対象となる全テキストは kishida.txt, ogawa.txt および santouka.txt の3つ)、オプション minFreq でterm となるための規定頻度 3 を指定し、pos で(形態素としての)termとなる品詞リストを名詞・形容詞・助詞と定めた上で、その検索語・文書行列 matrix を生成した結果である。 生成した matrix は長大なので head と tail を使って、 matrix の始まり20行と末尾20行のみを表示した。

> matrix <- docMatrix("text", minFreq = 3, pos = c("名詞", "形容詞", "助詞"))
file = text/kishida.txt
file = text/ogawa.txt
file = text/santouka.txt
Term Document Matrix includes 2 information rows! 
whose names are [[LESS-THAN-3]] and [[TOTAL-TOKENS]]
if you remove these rows, run
result[ row.names(result) !=  "[[LESS-THAN-3]]" , ]
result[ row.names(result) !=  "[[TOTAL-TOKENS]]" , ]
> head(matrix, 20)
                  docs
terms              kishida.txt ogawa.txt santouka.txt
  [[LESS-THAN-3]]           77        36           44
  [[TOTAL-TOKENS]]         150        79          142
  と                         4         0            0
  に                        13         3            0
  の                         4         5            8
  みな                       3         0            0
  を                         4         3            0
  町                         8         0            0
  飯田                       5         0            0
  が                         0         6            4
  て                         0         4            0
  から                       0         0            3
  は                         0         0            4
  ば                         0         0            3
  も                         0         0            6
  一                         0         0            4
  歩                         0         0            5
> tail(matrix, 20)
  [[LESS-THAN-3]]           77        36           44
  [[TOTAL-TOKENS]]         150        79          142
  と                         4         0            0
  に                        13         3            0
  の                         4         5            8
  みな                       3         0            0
  を                         4         3            0
  町                         8         0            0
  飯田                       5         0            0
  が                         0         6            4
  て                         0         4            0
  から                       0         0            3
  は                         0         0            4
  ば                         0         0            3
  も                         0         0            6
  一                         0         0            4
  歩                         0         0            5

各行の先頭(1列目)がtermで、2列目以降の数が文書ファイルごとの(形態素原形としての)termの出現頻度である。 検索語・文書行列を求めるときにオプション引数として minFreq = 3 の指定は、検索語・文書行列を構成するtermとなるための条件を指定している(無指定の場合にはデフォルト値 1 にセット)。 どれかの文書ファイルで、minFreq 回以上の頻度でなければ、検索語・文書行列のtermとして登場しない。 したがって、検索語・文書行列の各行の最大term頻度はminFreq 以上となること、および、(形態素原形としての)term頻度がある文書でminFreq 未満であるときには、term行のその文書における頻度は 0 となってしまう(実際にminFreq 回のterm頻度があったとしても 0になる)ことに注意しよう。 いいかえると、$minFreq \geqq 2$ と設定することは、ある(形態素原形としての)termを強調することになり(規定頻度 minFreq に達しないと 0 にしてしまう)、コントラストを高めた検索語・文書行列を求めることになる。 今の場合、1列目の[[LESS-THAN-3]] が示しているように、文書ファイル kishida.txt, ogawa.txt および santouka.txt に対して、各文書ファイルで2回以下しか登場しないtermの頻度合計がそれぞれ 77, 36 および 49 であったことがわかる。

一方、2列目の [[TOTAL-TOKENS]] はpos引数で指定しなかった品詞も含む、各文書テキストごとの形態素の全トークン数である(形態素原形の数ではない)。

先頭の[[LESS-THAN-3]]行と[[TOTAL-TOKENS]]行を削除して rmmatrix とするには次のようにする。

> rmmatrix <- matrix[row.names(matrix) !=  "[[LESS-THAN-3]]" , ]
> rmmatrix <- rmmatrix[row.names(rmmatrix) !=  "[[TOTAL-TOKENS]]" , ]
> head(rmmatrix)
      docs
terms  kishida.txt ogawa.txt santouka.txt
  と             4         0            0
  に            13         3            0
  の             4         5            8
  みな           3         0            0
  を             4         3            0
  町             8         0            0

また、文書全体で(形態素原形としての)termの登場頻度が4以上のtermだけを取り出すには、次のように列合計関数 rowSums( ) を使う。

> matrix2 <- rmmatrix[rowSums(rmmatrix) >= 4, ]
> head(matrix2, 20)
      docs
terms  kishida.txt ogawa.txt santouka.txt
  と             4         0            0
  に            13         3            0
  の             4         5            8
  を             4         3            0
  町             8         0            0
  飯田           5         0            0
  が             0         6            4
  て             0         4            0
  は             0         0            4
  も             0         0            6
  一             0         0            4
  歩             0         0            5

関数 docMatrix2 では、オプション引数 minFreq の意味が docMatricx とは異なり、全文書ファイルでの規定頻度となる。 docMatrix2(... , minFreq = n, ....) の結果は、docMatrix のオプション引数で minFreq = 1(無指定でもよい)とした結果において、各行の合計が n 以上の行を取り出した

> matrix <- docMatrix(... , minFreq = 1, ...) 
> matrix[rowSums(matrix) >= n, ]

で得られる結果に等しい。

関数 docMatrixDF は、テキスト文書ファイルからでなく、各列が文書情報からなる表データ(データフレームとして読み込まれる)の指定列から読み込んだ文書情報に対して、検索語・文書行列を返す。 各列がある質問に対する回答記述であるような表データ(自由記述アンケートなど)の場合に使う。

検索語・文書行列の重み付け 〜 TF・IDF法

先に求めた検索語・文書行列の要素 $tf_{jk}$ は、term(検索語)$t_j$ の文書ファイル $d_k$ に対するtermの登場頻度(term頻度 TF)で定義していた。 しかしながら、term頻度によって文書ファイル群におけるそのtermの重要性を測ることは難しい。 同じ内容傾向の文書であるならば、文書量に比例してそのterm頻度はいくらでも増大してしまうからだ。

term頻度から検索語・文書行列を定めるのではなく、その行列要素を以下のようにTF・IDF法(Term Frequency / Inverse Document Frequency)によって定めるやり方が今日広く用いられている。

文書頻度(DF: document frequency)とは、あるterm $t_j$ がいくつくらいの文書に現れるかの指標で \[ df_j = \mbox{term $t_j$ を含むの文書数} \] で定義される。

TF・IDF法は、term $t_j$ の文書 $d_k$ における指標 $w_{jk}$ を次のように定義して、検索語・文書行列の要素とするのである。 \[ w_{jk} = tf_{jk} \cdot \log\frac{N}{df_j}. \] ここで、$N$ は文書群における文書数で、対数の底は 2 である。 指標 $w_{jk}$ が大きくなるのは、term $t_j$ の文書 $d_k$ における頻度 $tf_{jk}$ が高く(その文書に何度も出現し)、かつ、そのtermの文書頻度 $df_j$ が低い(特定の文書にしか出現しない)場合である。 TF・IDF法とは、そのような(形態素原形としての)termを検索語に採用すべきだという基準を与えている。

関数 docMatrix で生成する検索語・文書行列をTF・IDF法で生成するには、次のようにオプション引数 minFreq を付けずに、引数 weight = "tf*idf" を指定する。

> matrix3 <- docMatrix("text", pos = c("名詞", "形容詞", "助詞"), weight = "tf*idf")
file = text/kishida.txt
file = text/ogawa.txt
file = text/santouka.txt
> head(matrix3, 20)
          docs
terms      kishida.txt ogawa.txt santouka.txt
  あかるい    2.584963  0.000000            0
  あつい      2.584963  0.000000            0
  いま        2.584963  0.000000            0
  おん        5.169925  0.000000            0
  か          3.169925  1.584963            0
  こそ        2.584963  0.000000            0
  さかしい    2.584963  0.000000            0
  さび        2.584963  0.000000            0
  そ          2.584963  0.000000            0
  それぞれ    2.584963  0.000000            0
  たち        2.584963  0.000000            0
  たま        2.584963  0.000000            0
  ちかい      2.584963  0.000000            0
  ちまた      2.584963  0.000000            0
  と          6.339850  1.584963            0
  ど          2.584963  0.000000            0
  として      2.584963  0.000000            0
  ども        2.584963  0.000000            0
  ない        1.000000  2.000000            2
  に         13.000000  3.000000            2
> tail(matrix3, 20)
        docs
terms    kishida.txt ogawa.txt santouka.txt
  どうし           0         0     2.584963
  とも             0         0     2.584963
  はけ             0         0     2.584963
  はて             0         0     2.584963
  も               0         0    15.509775
  よう             0         0     5.169925
  ワタ             0         0     2.584963
  意味             0         0     2.584963
  一寸             0         0     2.584963
  芽               0         0     2.584963
  語句             0         0     2.584963
  禅門             0         0     2.584963
  草               0         0     2.584963
  脱落             0         0     2.584963
  到着             0         0     5.169925
  道               0         0     2.584963
  仏               0         0     2.584963
  歩               0         0    12.924813
  木の芽           0         0     2.584963
  旅               0         0     2.584963

TF・IDF法による検索語・文書行列の規格化

TF・IDF法によって生成した検索語・文書行列について、各文書ベクトル(2列目からの各文書列 $\vec{dv_k}$ )の長さ $||\vec{dv_k}||$ を 1 にすることを規格化(normalization)という。

ベクトル $\vec{v} = (v_1,v_2,\dots, v_n)$ において、その長さ $||\vec{v}||$ を \[ ||\vec{v}|| = \sqrt{v_1^2+v_2^2+\dots+v_n^2} \] で定義する。 このとき、ベクトル $\vec{v}$ を規格化したベクトル $\vec{v'}$ は次のように表される。 \[ \vec{v'} = \left(\frac{v_1}{||\vec{v}||}, \frac{v_2}{||\vec{v}||}, \dots, \frac{v_n}{||\vec{v}||}\right). \]

TF・IDF法による検索語・文書行列を規格化するには、関数 docMatrix で、次のように引数 weight = "tf*idf*norm" を指定する。

> matrix4 <- docMatrix("text", pos = c("名詞", "形容詞", "助詞"), weight = "tf*idf*norm")
file = text/kishida.txt
file = text/ogawa.txt
file = text/santouka.txt
> head(matrix4, 20)
          docs
terms      kishida.txt  ogawa.txt santouka.txt
  あかるい  0.07467806 0.00000000   0.00000000
  あつい    0.07467806 0.00000000   0.00000000
  いま      0.07467806 0.00000000   0.00000000
  おん      0.14935613 0.00000000   0.00000000
  か        0.09157729 0.07450934   0.00000000
  こそ      0.07467806 0.00000000   0.00000000
  さかしい  0.07467806 0.00000000   0.00000000
  さび      0.07467806 0.00000000   0.00000000
  そ        0.07467806 0.00000000   0.00000000
  それぞれ  0.07467806 0.00000000   0.00000000
  たち      0.07467806 0.00000000   0.00000000
  たま      0.07467806 0.00000000   0.00000000
  ちかい    0.07467806 0.00000000   0.00000000
  ちまた    0.07467806 0.00000000   0.00000000
  と        0.18315458 0.07450934   0.00000000
  ど        0.07467806 0.00000000   0.00000000
  として    0.07467806 0.00000000   0.00000000
  ども      0.07467806 0.00000000   0.00000000
  ない      0.02888942 0.09402032   0.06566784
  に        0.37556244 0.14103049   0.06566784
> tail(matrix4, 20)
        docs
terms    kishida.txt ogawa.txt santouka.txt
  どうし           0         0   0.08487445
  とも             0         0   0.08487445
  はけ             0         0   0.08487445
  はて             0         0   0.08487445
  も               0         0   0.50924668
  よう             0         0   0.16974889
  ワタ             0         0   0.08487445
  意味             0         0   0.08487445
  一寸             0         0   0.08487445
  芽               0         0   0.08487445
  語句             0         0   0.08487445
  禅門             0         0   0.08487445
  草               0         0   0.08487445
  脱落             0         0   0.08487445
  到着             0         0   0.16974889
  道               0         0   0.08487445
  仏               0         0   0.08487445
  歩               0         0   0.42437223
  木の芽           0         0   0.08487445
  旅               0         0   0.08487445