読了: Wild (2016) Rのlsaパッケージでお手軽に潜在意味解析

 年末から家庭の事情に追いまくられ、ほとほと疲弊した。ようやく勤務先にも復帰し、徐々に日常を取り戻しつつあるけれど、頭に霞がかかったような感覚はいまだ消えない。参ったなあ。

Wild, F. (2016) Representing and Analysing Meaning with LSA. in “Learning Analytics in R with SNA, LSA, and MPIA“, Chap.4. Springer.

 仕事の都合でめくった奴。テキスト分析LSA(潜在意味解析)のRパッケージlsaについて、なにか簡単な紹介はないかな、と探してみつけたもの。著者はlsaパッケージの開発者。えーと、この先生は社会ネットワーク分析とLSAをあわせたMeaningful Purposive Interaction Analysis (MPIA)というのを提唱していて、その解説書のなかの一章らしい。

 いわく。
 意味表象を生成するテクニックのひとつとして、言語における語の共起を使って意味構造の情報を導出するというのがあって、「ヒューリスティック・ベース・アプローチ」とか「分布意味論」と呼ばれている。LSAはその方法のひとつである。社会ネットワーク分析で調べるような構造の特性はわかんないし、そもそも用いる特異値の数を事前に決められないんだけど、文章の意味を表現・分析する歴史あるアルゴリズムであります。
 [80年代末以降のLSAの歴史について… メモ省略]

1. 数学的基盤
 LSAの基礎となる原理は、文章をBoWベクトル空間表現にマップして…[文章で説明しているんだけどかえってややこしい。メモ省略]
 まず、、\(m\)個の単語(term)を行にとり、コーパスの\(n\)個の文書を列にとり、セルに出現頻度を入れた行列 \(M\)をつくる。これを文書-単語行列とかテキスト行列という。これを特異値分解し \(M=TSD^\top\)を得る。で、\(S\)から\(k\)個の値だけ取り出して\(T_k S_k D^\top_k = M_k\)とする。これが潜在意味空間ね。\(M\)の最小二乗的に最良の近似になっている。計算が大変なのは特異値分解するところである。
 新しい文書を既存の潜在意味空間に投影することもできる。これをfolding in と呼ぶ。新しい文書のベクトルを\(v\)として、投影した右特異ベクトルは \(d’ = v^\top T_k S_k{-1}\)、\(M_k\)における文書-単語ベクトルは\(m’ = T_k S_k d’^\top\)となるわけ。[しれっと書いてあるので確認せずにそのままメモしたけど、これで合っているのかな… ま、いずれ必要になったら考えよう]

 [ベクトル間の距離をどうやって測るかという話。コサイン距離とか。メモ省略]
 とはいえ、たとえばwolfとdog (意味論的には近い)の距離が近くなるとは限らない。asosicativeに近いのはむしろdogとcatかも。Landauer & Dumais(1997)はLSAで同義語のテスト問題が解けることを示したけど、あんまし過大評価しないように。コーパスをどう選ぶかに依存するからね。
 
2. lsaパッケージによる分析ワークフロー
 [ざっと目を通したけど、抽象的すぎてわかりにくい… メモは断念]

3. 分析例
 [Rコードつきで手順を示している。めんどくさくなってきたので読み飛ばした。でもあれね、新しい文字列から\(M_k\)に入っている単語を拾って文書ベクトルをつくる関数とか、それをfold inする関数とかもあるのね。こういうのは便利かもしれない]

4. TELにおけるLSAの応用の現状
 [ちゃんと読んでないのでTELってなんの略語だかわからないんだけど… technology-enhanced learningかな? まあ応用例がいろいろ書いてあるようだ。essay scoringとか。全然関心ないのでスキップ]

 こういう応用寄りの研究と並んで、LSAを意味表現理論として扱う基礎研究もある。そのはじまりはLandauer & Dumais(1997 Psych.Rev.)。その後Kintch(1998 Int.J.Psych.)が、時間と位置のスロットを持つ述語項構造からなる命題ネットワークを構築する代理物としてLSAを用いた。
 Landauer(1999 Disc.Proc.)はLSAに対するPerfetti(1998)の批判に抗して、意味の構築においては共起こそが基礎原理であると主張した。[…などなどと、Landeuer, Kintschらの文献が列挙されている。メモ省略。おいおい、Prefetti(1998)って参考文献に載ってないよ、ひどいなあ]

5. 自動的essay scoring
[Rコード付きで分析例を説明している。申し訳ないけどいまそういうの関心ないんです。スキップ]

6. LSAの限界
 内容分析の手法としてみたとき、LSAはなんといっても、目的関係・社会的関係と相互作用を分析する道具を持たない点が弱い。社会的ネットワーク分析を参照のこと。因子数を決める明確なルールがないという点も弱いですね。それらの克服についてはこの後の章をみてください。云々。
————
 めくってはみたものの、文章の上を目が滑っていくような感覚があって、全く頭に入らなかった。疲れているせいだろうか。
 ま、lsaパッケージの雰囲気はわかったので、まあこれでいいことにしよう。lsaパッケージのマニュアルをみたところ、主な関数として以下があるようだ。

  • textmatrix(): ファイルかディレクトリを受け取ってテキスト行列(文書-単語行列)をつくる。
  • lw_*(m), gw_*(m): テキスト行列mを受け取って重みづけしたテキスト行列を返す。たとえば、lw_logtf(m)は\(\log(m_{ij}+1)\)の行列を返す、という感じ。
  • lsa(x): テキスト行列から意味空間をつくる。次元数を指定できる。自動で決める方法もいくつかあるらしい。
  • as.textmatrix(LSAspace): lsa()で作った意味空間LSAspaceをテキスト行列に戻す。つまり元のテキスト行列の低ランク近似が帰ってくるってことですかね。何に使うんだろうか。
  • associate(textmatrix, term): テキスト行列textmatrixから単語termに近い単語を返す。
  • fold_in(docvecs, LSAspace): lsa()でつくった意味空間LSAspaceにテキスト行列docvecsをfold inする。
  • query(query, termlist): クエリ文queryから所与のテキスト行列へのクエリをつくる。termlistはテキスト行列の単語リスト。よくわからんが、たぶんここでクエリといっているのはBoWベクトルで、それをfold inしてからそれに近い文書をコサイン距離かなんかで探すのであろう。
  • getTriple(), setTriple(), delTriple(): ある文書, ある述語(“has_category”とか), ある目的語、の三つ組を定義できるらしい。なににつかうのかよくわからん。

日本語の場合は、形態素解析して単語を選んでテキスト行列をつくるところまでは当然ながら自力でやらねばいかんでしょうね。おそらくこのパッケージでいうテキスト行列の実態はrowname, colnameに文字列がはいったmatrixだと思うんだけど、その文字列が日本語であってもこのパッケージの関数はちゃんと動くのか、というのが疑問である。ま、試してみれば済む話だ。