Shogo's Blog

Nov 1, 2012 - 2 minute read - NLP CaboCha Python

PythonでCaboChaを美味しくいただく

日本語構文解析器CaboChaをPythonから使ってみたメモ.

インストール

CaboCha自体のインストールは公式のドキュメントを参照. ググれば他の人のレポートも出てくるはず.

CaboChaのソースコードを展開したディレクトリの中の pythonディレクトリにPython-bindingが入ってます. そこに移動した後,管理者権限で以下のコマンドを実行すればインストール完了.

python setup.py install

食べ方

解析結果を文字列出力

python/test.py に書いてあるとおり.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import CaboCha

# c = CaboCha.Parser("");
c = CaboCha.Parser()

sentence = "太郎はこの本を二郎を見た女性に渡した。"

print c.parseToString(sentence)

tree =  c.parse(sentence)

print tree.toString(CaboCha.FORMAT_TREE)
print tree.toString(CaboCha.FORMAT_LATTICE)

以下のような結果が得られれば成功.

<PERSON>太郎</PERSON>は-----------D
                     この-D       |
                       本を---D   |
                       二郎を-D   |
                           見た-D |
                           女性に-D
                           渡した。
EOS

<PERSON>太郎</PERSON>は-----------D
                     この-D       |
                       本を---D   |
                       二郎を-D   |
                           見た-D |
                           女性に-D
                           渡した。
EOS

* 0 6D 0/1 2.909358
太郎	名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー	B-PERSON
は	助詞,係助詞,*,*,*,*,は,ハ,ワ	O
* 1 2D 0/0 1.257926
この	連体詞,*,*,*,*,*,この,コノ,コノ	O
* 2 4D 0/1 0.638994
本	名詞,一般,*,*,*,*,本,ホン,ホン	O
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ	O
* 3 4D 1/2 1.696047
二	名詞,数,*,*,*,*,二,ニ,ニ	O
郎	名詞,一般,*,*,*,*,郎,ロウ,ロー	O
を	助詞,格助詞,一般,*,*,*,を,ヲ,ヲ	O
* 4 5D 0/1 0.000000
見	動詞,自立,*,*,一段,連用形,見る,ミ,ミ	O
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ	O
* 5 6D 0/1 0.000000
女性	名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ	O
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ	O
* 6 -1D 0/1 0.000000
渡し	動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ	O
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ	O
。	記号,句点,*,*,*,*,。,。,。	O
EOS

tree.toString(CaboCha.FORMAT_XML)でXML形式の出力も可能です.

<sentence>
 <chunk id="0" link="6" rel="D" score="2.909358" head="0" func="1">
  <tok id="0" feature="名詞,固有名詞,人名,名,*,*,太郎,タロウ,タロー" ne="B-PERSON">太郎</tok>
  <tok id="1" feature="助詞,係助詞,*,*,*,*,は,ハ,ワ" ne="O"></tok>
 </chunk>
 <chunk id="1" link="2" rel="D" score="1.257926" head="2" func="2">
  <tok id="2" feature="連体詞,*,*,*,*,*,この,コノ,コノ" ne="O">この</tok>
 </chunk>
 <chunk id="2" link="4" rel="D" score="0.638994" head="3" func="4">
  <tok id="3" feature="名詞,一般,*,*,*,*,本,ホン,ホン" ne="O"></tok>
  <tok id="4" feature="助詞,格助詞,一般,*,*,*,を,ヲ,ヲ" ne="O"></tok>
 </chunk>
 <chunk id="3" link="4" rel="D" score="1.696047" head="6" func="7">
  <tok id="5" feature="名詞,数,*,*,*,*,二,ニ,ニ" ne="O"></tok>
  <tok id="6" feature="名詞,一般,*,*,*,*,郎,ロウ,ロー" ne="O"></tok>
  <tok id="7" feature="助詞,格助詞,一般,*,*,*,を,ヲ,ヲ" ne="O"></tok>
 </chunk>
 <chunk id="4" link="5" rel="D" score="0.000000" head="8" func="9">
  <tok id="8" feature="動詞,自立,*,*,一段,連用形,見る,ミ,ミ" ne="O"></tok>
  <tok id="9" feature="助動詞,*,*,*,特殊・タ,基本形,た,タ,タ" ne="O"></tok>
 </chunk>
 <chunk id="5" link="6" rel="D" score="0.000000" head="10" func="11">
  <tok id="10" feature="名詞,一般,*,*,*,*,女性,ジョセイ,ジョセイ" ne="O">女性</tok>
  <tok id="11" feature="助詞,格助詞,一般,*,*,*,に,ニ,ニ" ne="O"></tok>
 </chunk>
 <chunk id="6" link="-1" rel="D" score="0.000000" head="12" func="13">
  <tok id="12" feature="動詞,自立,*,*,五段・サ行,連用形,渡す,ワタシ,ワタシ" ne="O">渡し</tok>
  <tok id="13" feature="助動詞,*,*,*,特殊・タ,基本形,た,タ,タ" ne="O"></tok>
  <tok id="14" feature="記号,句点,*,*,*,*,。,。,。" ne="O"></tok>
 </chunk>
</sentence>

しかし,このXML形式,&"<, >などの特殊記号を置換してくれないので, この結果をXMLのパーサに通す場合などは注意が必要.

そもそも標準の辞書ではこれらの文字を上手く扱えないので前処理を行ったほうがいいのかもしれない. 半角の&は辞書に登録されていおらず,全角の&にする必要がある.

Treeの中身をいじってみる

一度文字列に変換してしまうと色々面倒なことが起こりそうなので,Treeの中身を直接いじってみる. ドキュメントが無いのでcabocha.h の中身を見ながら試してみました.

#!/usr/bin/python
# -*- coding: utf-8 -*-

import CaboCha
c = CaboCha.Parser()

sentence = "太郎はこの本を渡した。"

tree =  c.parse(sentence)

for i in range(tree.chunk_size()):
    chunk = tree.chunk(i)
    print 'Chunk:', i
    print ' Score:', chunk.score
    print ' Link:', chunk.link
    print ' Size:', chunk.token_size
    print ' Pos:', chunk.token_pos
    print ' Head:', chunk.head_pos # 主辞
    print ' Func:', chunk.func_pos # 機能語
    print ' Features:',
    for j in range(chunk.feature_list_size):
        print chunk.feature_list(j),
    print
    print

for i in range(tree.token_size()):
    token = tree.token(i)
    print 'Surface:', token.surface
    print ' Normalized:', token.normalized_surface
    print ' Feature:', token.feature
    print ' NE:', token.ne # 固有表現
    print ' Info:', token.additional_info
    print ' Chunk:', token.chunk
    print