ページへ戻る

− Links

 印刷 

自然言語解析​/CaboChaをpythonで使う のバックアップソース(No.3) :: NJF Wiki

xpwiki:自然言語解析/CaboChaをpythonで使う のバックアップソース(No.3)

« Prev[5]  Next »[6]
*CaboChaとは [#o6e77da9]

CaboChaはどの単語がどの単語を修飾しているかなど、日本語の係り受け関係を解析するツール。
詳細は公式ページ[[https://taku910.github.io/cabocha/:https://taku910.github.io/cabocha/]]を参照のこと。

例えば

 echo "これは私のもっている赤いペンです"|cabocha

とすると、
      これは-----D
          私の-D |
      もっている-D
      赤いペンです
 EOS

とツリー出力される。これはわかりやすいようでそうでもない表現なので、より厳密な表示をさせるため「-f1」オプションをつけて実行しなおすと以下のようになります。

 echo "これは私のもっている赤いペンです"|cabocha -f1

 * 0 3D 0/1 -2.060711
 これ	名詞,代名詞,一般,*,*,*,これ,コレ,コレ
 は	助詞,係助詞,*,*,*,*,は,ハ,ワ
 * 1 2D 0/1 2.120296
 私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
 の	助詞,格助詞,一般,*,*,*,の,ノ,ノ
 * 2 3D 0/2 -2.060711
 もっ	動詞,自立,*,*,五段・タ行,連用タ接続,もつ,モッ,モッ
 て	助詞,接続助詞,*,*,*,*,て,テ,テ
 いる	動詞,非自立,*,*,一段,基本形,いる,イル,イル
 * 3 -1D 1/2 0.000000
 赤い	名詞,一般,*,*,*,*,赤井,アカイ,アカイ
 ペン	名詞,一般,*,*,*,*,ペン,ペン,ペン
 です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
 EOS

アスタリスクから始まる行がCaboChaの解析結果で、それ以外は形態素解析の結果です。ここではMecabを使っているので、その結果となっています。

一つ目の
 * 0 3D 0/1 -2.060711
を例にすると、各データの意味は以下の通りです。

-最初の0は文節の通番。文頭なので0
-3Dは数字の部分がその文節がかかっている通番。ここでは通番3の「赤いペンです」にかかっている。かかり先がなければ-1。よって文末は常に-1。Dの意味は資料がなく不明
-0/1の主辞(文節の中心となる単語)と機能語(助詞など)の位置を示している。この例では「私」が主辞で「の」が機能語
-次の小数値はかかりやすさの度合い

実際によく使うのは最初の通番と二番目のかかり先です。主辞/機能語は公式ページによると廃止も検討されています。かかりやすさの度合いは実際にどの程度精度に関わっているかは調査中だそうです。

よって上の例をまとめると、
-「これは」は「赤いペンです」にかかっている
-「私の」は「もっている」にかかっている
-「もっている」は「赤いペンです」にかかっている
-「赤いペンです」は文末なのでかかり先なし

となります。

コマンドライン引数で形態素解析のエンジンにパラメーターを渡すことも可能です。

 echo "おいしいチーズケーキをもらった"|cabocha -f1

の結果は

 * 0 1D 0/0 1.755362
 おいしい	形容詞,自立,*,*,形容詞・イ段,基本形,おいしい,オイシイ,オイシイ
 * 1 2D 1/2 1.755362
 チーズ	名詞,一般,*,*,*,*,チーズ,チーズ,チーズ
 ケーキ	名詞,一般,*,*,*,*,ケーキ,ケーキ,ケーキ
 を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
 * 2 -1D 0/1 0.000000
 もらっ	動詞,自立,*,*,五段・ワ行促音便,連用タ接続,もらう,モラッ,モラッ
 た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
 EOS

となって「チーズケーキ」が認識されないですが、例えば「 /usr/local/lib/mecab/dic/mecab-ipadic-neologd/」にmecab-ipadic-NEologdの辞書をインストールしておけば、

 echo "おいしいチーズケーキをもらった"|cabocha -f1 -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/

という風にmecabの「-d」オプションを使うことで、

 * 0 1D 0/0 1.656278
 おいしい	形容詞,自立,*,*,形容詞・イ段,基本形,おいしい,オイシイ,オイシイ
 * 1 2D 0/1 1.656278
 チーズケーキ	名詞,固有名詞,一般,*,*,*,チーズケーキ,チーズケーキ,チーズケーキ
 を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
 * 2 -1D 0/1 0.000000
 もらっ	動詞,自立,*,*,五段・ワ行促音便,連用タ接続,もらう,モラッ,モラッ
 た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
 EOS

と出力されます。

他にもいろいろなコマンドラインオプションがありますが、ここでは使わないので詳細は公式ページを参照してください。

*Pythonから使う [#o198f23f]

CaboChaはpythonから使うこともできます。インストール方法などは他にもたくさんの資料があるのでそちらにゆずるとして、使い方は、まずインポートして
 import CaboCha

次にパーサーを取得します。このとき前節のコマンドラインオプションと同様に、辞書を指定することもできます。

 c = CaboCha.Parser("-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd/")

あとはこのパーサーでパースします。
 parsed =  c.parse("これは私のもっている赤いペンです")

ツリー表示なども可能です。

 parsed =  c.parse("これは私のもっている赤いペンです")
 print parsed.toString(CaboCha.FORMAT_TREE)
      これは-----D
          私の-D |
      もっている-D
      赤いペンです
 EOS

注意しないといけないのは、パーサーは内部的にデータの保持はしてくれないことです。つまり

 parsed =  c.parse("これは私のもっている赤いペンです")
 parsed2 = c.parse("おいしいチーズケーキをもらった")
 print parsed.toString(CaboCha.FORMAT_TREE)

とすると結果は
      おいしい-D
  チーズケーキを-D
          もらった
 EOS

となり変数parsed2に結果を格納したつもりでも、parsedの方も書きかわってしまいます。そのため、パースしたその結果を保持したければ、自分で他の変数に結果を移さなければなりません。

そのためにはパース結果からデータを取り出す必要があります。
パーサーが返す結果には次のメソッドがあります。

まず文節のデータに関しては

|メソッド名|引数|概要|
|chunk|整数|引数番目の文節のデータを取得する|
|chunk_size|なし|文節の個数を取得する|

一方、形態素解析のデータに関しては

|メソッド名|引数|概要|
|token|整数|引数番目の形態素のデータを取得する|
|token_size|なし|形態素の個数を取得する|

というメソッドがあります。

よって文節のデータを全て取り出すには、先ほどパースした「parsed」に対して以下のようにします。

 for i in range(parsed.chunk_size()):
     chunk = parsed.chunk(i)

このとき取り出した一つ一つのデータ(上の例ではchunk)には以下のプロパティがあります。

|プロパティ名|概要|
|score|かかりやすさの度合い|
|link|文節がかかっている通番|
|token_size|含まれる形態素の数|
|token_pos|含まれる形態素の先頭の場所|
|head_pos|主辞の場所|
|func_pos|機能語の場所|

ほとんどのプロパティは前節のコマンドラインで実行した例で解説しているので、分からないところは戻って確認してください。token_posは例えば

 first_token = parsed.token(chunk.token_pos)

とするとその文節の最初の形態素が取得できます。

一方、tokenつまり形態素解析の結果についてはMecabのpythonバインディングと全く同じ格納のされかたをされています。詳細は[[自然言語解析/MeCabをpythonで使う]]を参照してください。

例えば

 print token.surface

とすれば元の単語が表示されます。
よって

 for i in range(parsed.chunk_size()):
     chunk = tree.chunk(i)
     for j in range(chunk.token_size):
             token = parsed.token(chunk.token_pos + j)
             print token.surface,

とすると、元の文章が空白区切りで出力されます





&font(Red){編集中};

« Prev[5]  Next »[6]