<< 目次へ
最終更新日:2010.6.16
テキストマイニングの基礎
Contents
|
まずRをインストールしておくこと(不慣れな人は丁寧に解説したRインストールのページを参照のこと)。
Rでテキストマイニングをするために石田基広氏のウェブサイトよりRMeCab_0.90.zipというファイルをダウンロードする。ファイル名は変更されるかもしれないし、0.90というバージョンも変わるかもしれないので最新のものをダウンロードすること。なおダウンロードされた.zipファイル(圧縮されたファイル)は解凍する必要がなく、.zipファイルをそのまま適当なディレクトリ(フォルダ)に置いておけばよい。
Rのワークディレクトリ(getwd()とコマンドすれば確認できる)に、例えばzip_packagesという名前のフォルダを作成しておき、その中に保存しておくと分かりやすいだろう。 |
〜R上での準備〜
R上でRMeCabを利用するためには
[パッケージ] -> [ローカルにあるzipファイルからのパッケージのインストール...]
と選択していき、先ほど用意したzip_packagesというフォルダ内にあるRMeCab_0.90.zipを選択すればよい(以下に示すようにコマンドしてもよい)。それで「パッケージ’RMeCab’は〜」というメッセージが表示されれば、正常にパッケージがインストールされたということである。これに続けて、さらに library(RMeCab) とコマンドしてパッケージを読み込む必要がある。
> utils:::menuInstallLocal() パッケージ 'RMeCab' は無事に開封され、MD5 サムもチェックされました > library(RMeCab)
なお、新しいバージョンのRをインストールするたびにパッケージは別途(改めて)インストールしなければならない。パッケージの読み込みはRを新たに起動させる度に呼び出さないとならない、ということに注意しておこう。
〜形態素解析〜
Rでテキストマイニングを行う前に形態素解析の基本を理解しておかなければならないだろう。例えば以下の一文を見てみよう。
私は彼女のことを深く愛している。 |
とても単純な文章だが、この一文には名詞、動詞、形容詞や助詞、それから句点(。)が含まれている。RMeCabでは、句点や読点は記号として分類されるが、こうした名詞や動詞といった品詞ごとに文章を分解することを形態素解析という。
私 | は | 彼女 | の | こと | を | 深く | 愛し | て | いる | 。 |
名詞 | 助詞 | 名詞 | 助詞 | 名詞 | 助詞 | 形容詞 | 動詞 | 助詞 | 動詞 | 記号 |
〜Rで形態素解析を行う〜
RMeCabパッケージにはRMeCabC()という関数が含まれており、これは先に述べた形態素解析を行うための関数である。R上では以下のようにコマンドすればよいが、テキストマイニングを行う際にはフォントをMS Gothic(MS ゴシック)にしておいた方がよい。私はCourier Newを好んで使っているが、これだと日本語がウィンドウ上で上手く表示されない。
> moji <- "私は彼女のことを深く愛している。" > RMeCabC(moji) [[1]] 名詞 "私" [[2]] 助詞 "は" ・・・(途中省略)・・・ [[10]] 動詞 "いる" [[11]] 記号 "。"
テキストマイニングで最も基本的な解析法は、ある単語の出現頻度を調べることであろう。ここでは以下のテキストデータを用いてみよう。
主人公の七海るちあ(マーメイドの少女)のボーイフレンドである堂本海斗(どうもとかいと)は小さい頃の自分を思い出すためにハワイへ留学するが、そこでマーメイドと海に関する記憶を失ってしまう。それである日、海斗はるちあの通っている学校(マーメイドは人型になって学校に通っているという設定である)に帰ってきたのだが、記憶を失っている海斗はるちあのことを全く思い出せず、るちあは「ひどいよ海斗〜」みたいな展開になる。それからるちあは海斗の記憶を取り戻すために色々やってみたり、海斗も自分自身の記憶を取り戻そうとするわけだ。結局、海斗はミケル(いわゆる最後のボス)に記憶を読まれないために自分でマーメイドに関する記憶を封印したことがわかるのであるが、、、 |
まずこれを pich.txt というテキストファイルとして適当なディレクトリに置いておく。できればRのワークディレクトリ(getwd()で得られる)に置いておくことをおススメするが、それ以外のディレクトリに置いてあったとしても問題はない。
単語の出現頻度をデータフレームとして出力するのがRMeCabC()という関数であり、引数に先ほど用意した pich.txt を指定すればよいだけである。ただし、ファイル名は(a)拡張子を含めること、(b)ダブルクォーテーション(" ")で括る、ということを忘れてはならない。また、Rのワークディレクトリにテキストファイルが保存されていない場合、ファイルが置いてあるパスを全て記述する必要がある。
> # ワークディレクトリに保存されている場合 > txres <- RMeCabFreq("pich.txt") > # ワークディレクトリに保存されていない場合 > txres <- RMeCabFreq("C://***/***/pich.txt")
上のコマンドはRMeCabC()が返すデータフレーム形式の結果をtxresという変数(オブジェクト)に代入したことを意味している。だからtxresには次のような結果が格納されているのだということを確認することができる。
> txres Term Info1 Info2 Freq 1 あ フィラー * 2 2 あ 感動詞 * 1 3 〜 記号 一般 1 4 ( 記号 括弧開 4 ・・・(以下省略)・・・
一般に大量のテキストデータを扱うことになるので、出力が100行以上になることも珍しくない。そこで出現頻度(Freq)が5以上であるものだけを表示させたい場合、次のようにコマンドすればよい。
> txres[txres$Freq >= 5, ] Term Info1 Info2 Freq 9 、 記号 読点 9 16 に 助詞 格助詞 8 19 を 助詞 格助詞 8 20 は 助詞 係助詞 5 24 て 助詞 接続助詞 7 28 の 助詞 連体化 7 32 だ 助動詞 * 7 39 ちる 動詞 自立 5 60 記憶 名詞 サ変接続 6 68 海 名詞 一般 7 76 斗 名詞 一般 7
さらに助詞や記号などの不要なものを除き、例えば名詞だけを表示させたい場合、あるいは名詞と動詞のみを表示させたい場合は次のようにコマンドする。
> 頻度が5以上、かつ品詞が名詞であるものだけを表示させる > txres[txres$Freq >= 5 & txres$Info1 == "名詞", ] Term Info1 Info2 Freq 60 記憶 名詞 サ変接続 6 68 海 名詞 一般 7 76 斗 名詞 一般 7 > # 頻度が5以上、かつ(名詞もしくは動詞である)ものだけを表示させる > txres[txres$Freq >= 5 & (txres$Info1 == "名詞" | txres$Info1 == "動詞"), ] Term Info1 Info2 Freq 39 ちる 動詞 自立 5 60 記憶 名詞 サ変接続 6 68 海 名詞 一般 7 76 斗 名詞 一般 7
頻度表より出現頻度の高い単語が確認できた場合、その単語に隣接した単語にも関心が出てくるだろう。なぜならば、その単語の前後にも重要な情報がある場合が多いからである。例えば父親の評価を求めた場合、「父親」という単語の前には「やさしい」や「厳しい」という回答者の父親の性質(性格)が記述されているかもしれない。あるいは単語の後に「怒られた」とか「出かけた」といったように、父親が何をしたのかという行動が記述されているかもしれないからである。
こういったある単語に隣接して現れる単語のことを共起語といい、その中心となる単語のことを中心語という。中心語のことをキーワードやノードということもある。また、中心語に隣接している"単語の範囲"をスパンという。例えば「私の趣味はスキーです。」という文章について、趣味を中心語とし、スパンを1とした場合の共起語は「の」と「は」である。スパンが2ならば「私」「の」と「は」「スキー」になる。
2 | 1 | 中心語 | 1 | 2 | ||
私 | の | 趣味 | は | スキー | ||
名詞 | 助詞 | 名詞 | 助詞 | 名詞 |
実際に上記2つの文章のうち、1つ目の「会社では〜」という一文を father.txt として保存しておき、collocate()を用いた共起語分析を実行してみよう。この関数の第1引数にはファイル名を、第2引数には中心語を、そして第3引数にスパンを指定する。ただし、結果の出力には「父親」という中心語も含まれていることに注意しなければならない。
> 中心語を「父親」とし、スパン(単語の範囲)を1として解析 > txres <- collocate("father.txt", node="父親", span=1) file = father.txt length = 16 > txres Term Before After Span Total 1 も 0 1 1 1 2 厳しい 1 0 1 1 3 父親 1 0 1 1 4 [[MORPHEMS]] 2 1 3 16 5 [[TOKENS]] 2 1 3 17
これは短い例文が一文だけなので共起頻度(Totalで表されている)が少ない。しかし大量のテキストデータを扱う場合にはもっとたくさんの共起回数が得られるかもしれない。そのようなとき、共起頻度が有意に大きいかどうかを確かめるためにt値やMI値といった指標が参考になる。これらの指標はcollScores()という関数で得られる。第1引数にはcolloccate()の返す結果が格納されているオブジェクトを、第2引数と第3引数にはcollocate()のときと同じく中心語とスパンを指定する。
> txres2 <- collScores(txres, node="父親", span=1) > txres2 Term Before After Span Total T MI 1 も 0 1 1 1 0.882353 3.087463 2 厳しい 1 0 1 1 0.882353 3.087463 3 父親 1 0 1 1 NA NA 4 [[MORPHEMS]] 2 1 3 16 NA NA 5 [[TOKENS]] 2 1 3 17 NA NA
一般的にt値が1.65以上あれば共起頻度が有意に大きかったと判断してよいそうです。あまりt値やMI値にこだわる必要はなく、目安の1つとして見たほうがよさそうです。
共起語分析とも似ている部分がありますが、ある単語がどのような文脈で出現するのかを調べるために役立つのがNgram解析です(いつの間にか「です・ます調」になっていますが気にしないでください ^^; )。NgramのNは任意の数Nという意味のNであり、gramはギリシャ語で「書かれたもの」という意味です。共分散構造分析でパス図のことをパスダイアグラム(Path Diagram)といいますが、そのgramと同じです。要するに「N個の書かれたもの」を解析するというものです。
例えば先にあげた「私の趣味はスキーです。」をN=2として、「2個の書かれたもの」に書き直してみると次のようになります。
私 | の |
の | 趣味 |
趣味 | は |
は | スキー |
スキー | です |
です | 。 |
これをN=3として、つまり「3個の書かれたもの」に直してみると次のようになります。
私 | の | 趣味 |
趣味 | は | スキー |
スキー | です | 。 |
以上のように「N個の単語の連なり」を一単位(一区切り)として書き表したものをNgramというわけですが、特にN=2の場合にバイグラム、N=3のときはトライグラムと呼ばれます。語源は知りませんが、バイリンガルのバイ(2ヶ国語を使いこなす人)やトライリンガルのトライ(3ヶ国語を使いこなす人)と同じです。ちなみに1の場合はユニ、4の場合はテトラ(テトラポットのテトラです)といいます。また、面倒くさい話ですが、上記の例は形態素単位でのNgramであり、文字単位、あるいは品詞情報単位でNgramを作ることもできます。
ともかくこのNgram解析を用いることで、ある単語の前後の文脈が把握できるようになります。最初に用いた pich.txt を対象にNgram解析を行ってみましょう。用いる関数はNgram()で、第1引数にはテキストファイル名を、第2引数にはtype=1とし、第3引数としてpos="名詞"、そして第4引数にNを指定します。ここで第2引数として指定したtypeには0、1、2のいずれかを指定することができます。0ならば文字単位、1なら形態素単位、2は品詞情報単位で解析を行います(省略した場合は0と指定したことになります)。それからposには自由な品詞を指定することができます。例えば名詞と動詞を指定したければpos=c("名詞", "動詞")とします(省略した場合は名詞と形容詞を指定したことになります)。それからNはNgramのNを指定するもので、省略した場合はN=2とした場合と同じになります。トライグラムならばN=3とします。
> txres <- Ngram("pich.txt", type=1, pos="名詞", N=2) file = pich.txt Ngram = 2 length = 51 > txres Ngram Freq 1 [こと-の] 1 2 [こと-海] 1 3 [それ-日] 1 ・・・(途中省略)・・・ 48 [堂本-海] 1 49 [日-海] 1 50 [封印-こと] 1 51 [留学-マーメイド] 1
なおNgramDF()という関数があり、これを用いた場合には、結果がデータフレームとして結果が返されます。使い方はNgram()と全く同じです。
> txres <- NgramDF("pich.txt", type=1, pos="名詞") file = pich.txt Ngram = 2 > txres Ngram1 Ngram2 Freq 1 こと の 1 2 こと 海 1 3 それ 日 1 ・・・(途中省略)・・・ 48 堂本 海 1 49 日 海 1 50 封印 こと 1 51 留学 マーメイド 1
他の統計理論をテキストマイニングに応用した方法としてテキストのネットワーク分析があります。
これを行うために、まずパッケージigraphをインストールして呼び出しておく必要があります。
> install.packages("igraph") > library(igraph)
手順としては(1)NgramDF()でNgram解析の結果をデータフレームとして用意しておき、(2)graph.data.frame()でネットワーク図を出力するためのオブジェクトを作成する、ということになります。
> # Ngram解析の結果をデータフレームとしてオブジェクトに格納しておく > tx.ngram <- NgramDF("pich.txt", type=1, pos="名詞", N=2) file = pich.txt Ngram = 2 > # ネットワーク図を描くためのオブジェクトを用意する > tx.net <- graph.data.frame(tx.ngram) > # 中身を確認してみる > tx.net Vertices: 31 Edges: 51 Directed: TRUE Edges: [0] 'こと' -> 'の' [1] 'こと' -> '海' [2] 'それ' -> '日' [3] 'ため' -> 'ハワイ' ・・・(途中省略)・・・ [48] '日' -> '海' [49] '封印' -> 'こと' [50] '留学' -> 'マーメイド' > # 単にプロットしたければこれだけでOK > plot(tx.net) > # ラベルを描く場合 > plot(tx.net, vertex.label=V(tx.net)$name) > # さらにラベルスタイルを変更する場合 > plot(tx.net, vertex.label=V(tx.net)$name, vertex.size=1)
ちょっとしたコツとして、一般にネットワーク図を書いてみてもゴチャゴチャしすぎていて何も有益な情報が読み取れないことが多い。そこでNgram解析で得られた結果について、頻度(Freq)が2以上のものだけをネットワーク分析の対象にすることでシンプルな図に出来上がることがある。ここで2以上というのはあくまでも目安で、4以上でもよいし、10以上でもよい(それは分析者自身が適当に決めるべきである)。
> # 頻度が2以上のものだけを対象にする > tx.net <- graph.data.frame(tx.ngram[tx.ngram$Freq > 2,]) > plot(tx.net, vertex.label=V(tx.net)$name, vertex.size=1)
ネットワーク図はシンプルすぎても複雑すぎてもいけない。そこでNgram解析の際に指定する品詞を名詞と形容詞にしてみるとか、Nの数を2から3にしてみるという工夫も必要になってくる。もちろん前述したように頻度がいくつ以上のものを解析の対称にするかも重要である。経験からいって、ネットワーク図がシンプルすぎる場合は別の品詞を加えてみる必要があり、複雑すぎる場合はより高い頻度のものだけを解析対象に絞る必要が多い場合がほとんどである。