2016年5月14日土曜日

共起関係の表示

前回まで、N-gramで隣接する文字の間、あるいは隣接する単語の間の共起関係を求めました。でも、例えば、「風の又三郎」でbi-gramを求めると、その数は「名詞」と「形容詞」だけでも4千組近くあります。これがたとえ100組くらいに減ったとしても、これ全体を確認するのは骨が折れます。で、この共起関係を図にできれば、状況を一望できるでしょう。Rは図の表示に関しても、便利な関数を備えています。
igraphというパッケージを使って、「風の又三郎」のbi-gramを図にしてみましょう。例によって、「風の又三郎」のテキストファイルがフォルダNORUBYの中にあるものとします。ない、という方は、前回までの「Rあれこれ」を参照して下さい。
で、まず、「風の又三郎」を読み込んで、bi-gramを求めます。ただし、今回は形容詞も含めることにします。
> library(RMeCab)
> ngr2 <- NgramDF("NORUBY/kazeno_matasaburo2.txt", type = 1, pos = c("名詞","形容詞") )
file = NORUBY/kazeno_matasaburo2.txt Ngram = 2
> head(ngr2)
  Ngram1     Ngram2 Freq
1   あい     あいだ    1
2   あい       そこ    1
3   あい       づあ    1
4   あい づやっぱり    1
5   あい       一郎    1
6   あい       嘉助    1
>
次に、igraphパッケージを読み込みます。igraphは、インタラクティブにグラフを操作する機能を持つ関数群です。グラフに表示するとき、数が多いとゴチャゴチャするので、まず、bi-gramの頻度が3以上のものを抽出します。で、データフレーム形式をネットワークグラフを扱う形式に変換します。
> library(igraph)
> ngr2limit <- ngr2[ngr2[,3] > 2 , ]
> bigraph<-graph_from_data_frame(ngr2limit)
> tkplot(bigraph, vertex.color = "Yellow", vertex.size = 20)
[1] 4
>
このtkplotというのを実行すると、別画面にグラフが表示されるでしょう。表示が偏っている場合は、ポップアップした別画面のメニューでView > Fit to screenとやると、画面全体に表示されます。このグラフでは、名詞や形容詞の関係を矢印で示しています。

2016年5月1日日曜日

N-gram

前回まで、tf-idfを求めて特徴ベクトルとし、文書の比較を行いました。文書を特徴づける指標は他にもあります。少し前に共起性というのがありました。隣接する単語の共起性を指標にするものとして、N-gramがあります。N-gramは、文書の中でN個の文字あるいは単語の組合せが、どの程度出現するかを調べます。これは、その文字あるいは単語の発生確率が直前の文字や単語に依存すると考えているからです。
例えば、「私はRを勉強しています」という文章があったとして、N=1(uni-gram)ならば、各文字が一つずつ出現することが得られます。N=2(bi-gram)ならば、「私は」「はR」「Rを」というように、2文字の組みで出現することを得ます。この文字の組は、共起関係と言います。この共起関係がどの程度の頻度で出現するかを調べたのが、共起頻度です。で、共起頻度がわかると、何が嬉しいかが問題ですよね。例えば、共起頻度を調べて文書の性質を見つけたり、ある文字列の直後に来やすい文字列を求めたり、音声認識なんかで訂正するときの情報として利用したりします。
では、RでN-gramを実行してみましょう。例文として、前回読み込んだ「風の又三郎」「セロ弾きのゴーシュ」「注文の多い料理店」を使います。フォルダ「NORUBY」の中に「kazeno_matasaburo2.txt」などのファイルが置いてあるものとします。このテキストファイルがない、という方は、前回までの「Rあれこれ」を見てご用意下さい。
> library(RMeCab)
> ngr1 <- Ngram("NORUBY/kazeno_matasaburo2.txt", type = 1)
file = NORUBY/kazeno_matasaburo2.txt Ngram = 2
length = 3967
> head(ngr1)
              Ngram Freq
1     [あい-あいだ]    1
2       [あい-そこ]    1
3       [あい-づあ]    1
4 [あい-づやっぱり]    1
5       [あい-一郎]    1
6       [あい-嘉助]    1
>

Ngramという関数が、N-gramを求めるものです。第1引数はファイル名で、第2引数が形態素のN-gramを求めることを指定しています。もし、第2引数を省略すると、文字の間のNgramを求めることになります。Ngram = 2 と表示されていますように、bi-gramを求めています。
関数Ngramでは[あい-一郎]というように、形態素の組で表示されました。形態素ごとに分けて表示したい場合、関数NgramDFを使います。
> ngr2 <- NgramDF("NORUBY/kazeno_matasaburo2.txt", type = 1, pos = "名詞")
file = NORUBY/kazeno_matasaburo2.txt Ngram = 2 
> head(ngr2)
  Ngram1     Ngram2 Freq
1   あい     あいだ    1
2   あい       そこ    1
3   あい       づあ    1
4   あい づやっぱり    1
5   あい       一郎    1
6   あい       嘉助    1
>
pos = "名詞"というのは、「名詞」だけ抽出しているということです。これを指定しないと、名詞と形容詞の形態素が抽出されます。
関数NgramDF2を使えば、第1引数にフォルダを指定してその中に含まれるファイルをすべて対象にできます。引数minFreqは、頻度の最低値を指定します。
> ngr3 <- NgramDF2("NORUBY", type = 1, pos = "名詞", minFreq=2)
file_name =  NORUBY/chumonno_oi_ryoriten2.txt opened
file_name =  NORUBY/kazeno_matasaburo2.txt opened
file_name =  NORUBY/serohikino_goshu2.txt opened
number of extracted terms = 727
> head(ngr3)
  Ngram1 Ngram2 chumonno_oi_ryoriten2.txt kazeno_matasaburo2.txt serohikino_goshu2.txt
1 あいつ     風                         0                      2                     0
2 あっち こっち                         0                      3                     0
3   あと   あと                         0                      2                     0
4   あと   だい                         0                      3                     0
5   あと   よう                         0                      0                     2
6   あと     一                         0                      2                     0
>

結果を見ると、「風の又三郎」「セロ弾きのゴーシュ」「注文の多い料理店」では隣接する単語の組がまったく違っています。まあ、当然と言えば当然ですが、この違いは作品の特徴の一つの指標と考えることができます。つまり、その文書の特徴を表すキーワードというわけです。逆に、3つの作品に共通する単語の組が抽出できれば、その作者特有のキーワードが抽出できるかも知れません。注意しなければいけないのは、文書に含まれる文字数が文書によって違っているという点です。比較するなら、頻度を正規化する操作が必要でしょうね。