Edited at

CaboChaで係り受け解析

More than 5 years have passed since last update.

cabochaを使って日本語の係り受けを調べるコードを作ってみました。

とりあえず名詞と形容詞の関係の抽出をしてみました。


参考文献

CaboChaのwindows環境へのinstallなどはmima_itaさんのブログを参考にして頂ければと思います。

WindowsにCabochaをいれてPythonで係り受けを解析してみる


品詞と語の順を簡単にまとめてみる

自然言語について専門的に勉強した事はありませんし、論文等で調査したわけではなく、たんなる素人の発想を以下に記載致します。

名詞、動詞、形容詞に絞って、単純に直前の語の品詞との関係を考えると以下のようなパターンにわけられると思います。


  • 名詞 → 名詞:「○○が□□を見た」のように、後ろの名詞が対象を表す

  • 名詞 → 動詞(→ 名詞):「○○が見た□□は」のように、主語の動作または対象となる後ろの名詞に対する動作を表す

  • 名詞 → 形容詞:「○○は美しい」のように、対象となる語を修飾する

  • 形容詞 → 名詞:「美しい○○」のように、対象となる語を前から修飾する

これを元に名詞と形容詞の関係性を取得するコードを作成しました。

以下、コードを記載致します。


参考コード

# coding: utf-8


import CaboCha
import xml.etree.ElementTree as ET
from collections import defaultdict

def get_reputation(ET_tree):
flag = None
reputation = defaultdict(str)

for el in ET_tree.findall(".//chunk"):
tok = el.find("tok")
feature = tok.attrib["feature"].strip().split(',')
part = feature[0]
typ = feature[1]

if part=='名詞' and \
(typ=='一般' or typ=='固有名詞'):
reputation["object"]=tok.text
if part=='形容詞': reputation['adjective']=feature[6]
link = el.attrib["link"]
if link=='-1': break
while 1:
res = get_next_chunk(link,part)
if res==None: break
part, typ, word, link = res

if part=='名詞' and \
(typ=='一般' or typ=='固有名詞'):
reputation["object"]=word
if part=='形容詞':
reputation['adjective'] = word
if reputation["object"]!=None:
flag=1
break
if flag==1: break

print reputation["object"]
print reputation["adjective"]

def get_next_chunk(linkid, ex_part):
if linkid=='-1': return None
this_chunk = ET_tree.find(".//chunk[@id='%s']" % linkid)
#print this_chunk.attrib
link = this_chunk.attrib["link"]

tok = this_chunk.find('tok')
feature = tok.attrib["feature"].strip().split(',')
if ex_part=='名詞':
if feature[0]=='名詞':
return feature[0], feature[1], tok.text, link
elif feature[0]=='動詞' or feature[0]=='形容詞':
return feature[0], feature[1], feature[6], link
elif ex_part=='動詞':
if feature[0]=='名詞':
return feature[0], feature[1], tok.text, link
elif ex_part=='形容詞':
if feature[0]=='名詞':
return feature[0], feature[1], tok.text, link

if __name__=='__main__':
c = CaboCha.Parser('--charset=UTF8')

sentence = "クーリエの6月号「楽しく学ぶ『教養』入門」で一番おもしろかったのは、池上英洋さんの記事。「絵画の見かた」って超絶大事だよね。"

tree = c.parse(sentence)
#print tree.toString(CaboCha.FORMAT_TREE)
#print tree.toString(CaboCha.FORMAT_LATTICE)
print tree.toString(CaboCha.FORMAT_XML)
ET_tree = ET.fromstring(tree.toString(CaboCha.FORMAT_XML))

get_reputation(ET_tree)

各チャンク毎に先頭のtokしか取得していませんが、これは、上手くチャンクに分けることが出来れば先頭のtokに意味のある語が来るはずだからです。


出力結果

『クーリエの6月号「楽しく学ぶ『教養』入門」で一番おもしろかったのは、池上英洋さんの記事。「絵画の見かた」って超絶大事だよね。』

って文をCaboChaで解析してみました。

CaboChaの解析結果をXML出力したモノは以下になります。



<sentence>

<chunk id="0" link="1" rel="D" score="0.328005" head="0" func="1">

<tok id="0" feature="名詞,一般,*,*,*,*,*,*,*,Wikipedia">クーリエ</tok>

<tok id="1" feature="助詞,連体化,*,*,*,*,の,ノ,ノ">の</tok>

</chunk>

<chunk id="1" link="4" rel="D" score="0.018011" head="3" func="3">

<tok id="2" feature="名詞,副詞可能,*,*,*,*,6月,ロクガツ,ロクガツ">6月</tok>

<tok id="3" feature="名詞,接尾,一般,*,*,*,号,ゴウ,ゴー">号</tok>

</chunk>

<chunk id="2" link="3" rel="D" score="1.140087" head="5" func="5">

<tok id="4" feature="記号,括弧開,*,*,*,*,「,「,「">「</tok>

<tok id="5" feature="形容詞,自立,*,*,形容詞・イ段,連用テ接続,楽しい,タノシク,タノシク">楽しく</tok>

</chunk>

<chunk id="3" link="4" rel="D" score="2.891449" head="6" func="6">

<tok id="6" feature="動詞,自立,*,*,五段・バ行,基本形,学ぶ,マナブ,マナブ">学ぶ</tok>

</chunk>

<chunk id="4" link="6" rel="D" score="1.654218" head="10" func="12">

<tok id="7" feature="記号,括弧開,*,*,*,*,『,『,『">『</tok>

<tok id="8" feature="名詞,一般,*,*,*,*,教養,キョウヨウ,キョーヨー">教養</tok>

<tok id="9" feature="記号,括弧閉,*,*,*,*,』,』,』">』</tok>

<tok id="10" feature="名詞,サ変接続,*,*,*,*,入門,ニュウモン,ニューモン">入門</tok>

<tok id="11" feature="記号,括弧閉,*,*,*,*,」,」,」">」</tok>

<tok id="12" feature="助詞,格助詞,一般,*,*,*,で,デ,デ">で</tok>

</chunk>

<chunk id="5" link="6" rel="D" score="2.796273" head="13" func="13">

<tok id="13" feature="名詞,副詞可能,*,*,*,*,一番,イチバン,イチバン">一番</tok>

</chunk>

<chunk id="6" link="8" rel="D" score="1.346988" head="16" func="17">

<tok id="14" feature="形容詞,自立,*,*,形容詞・アウオ段,連用タ接続,おもしろい,オモシロカッ,オモシロカッ">おもしろかっ</tok>

<tok id="15" feature="助動詞,*,*,*,特殊・タ,基本形,た,タ,タ">た</tok>

<tok id="16" feature="名詞,非自立,一般,*,*,*,の,ノ,ノ">の</tok>

<tok id="17" feature="助詞,係助詞,*,*,*,*,は,ハ,ワ">は</tok>

<tok id="18" feature="記号,読点,*,*,*,*,、,、,、">、</tok>

</chunk>

<chunk id="7" link="8" rel="D" score="3.189624" head="21" func="22">

<tok id="19" feature="名詞,固有名詞,人名,姓,*,*,池上,イケガミ,イケガミ">池上</tok>

<tok id="20" feature="名詞,固有名詞,人名,名,*,*,英洋,ヒデヒロ,ヒデヒロ">英洋</tok>

<tok id="21" feature="名詞,接尾,人名,*,*,*,さん,サン,サン">さん</tok>

<tok id="22" feature="助詞,連体化,*,*,*,*,の,ノ,ノ">の</tok>

</chunk>

<chunk id="8" link="11" rel="D" score="-0.885691" head="23" func="23">

<tok id="23" feature="名詞,一般,*,*,*,*,記事,キジ,キジ">記事</tok>

<tok id="24" feature="記号,句点,*,*,*,*,。,。,。">。</tok>

</chunk>

<chunk id="9" link="10" rel="D" score="4.381583" head="26" func="27">

<tok id="25" feature="記号,括弧開,*,*,*,*,「,「,「">「</tok>

<tok id="26" feature="名詞,一般,*,*,*,*,絵画,カイガ,カイガ">絵画</tok>

<tok id="27" feature="助詞,連体化,*,*,*,*,の,ノ,ノ">の</tok>

</chunk>

<chunk id="10" link="11" rel="D" score="-0.885691" head="29" func="31">

<tok id="28" feature="動詞,自立,*,*,一段,連用形,見る,ミ,ミ">見</tok>

<tok id="29" feature="名詞,接尾,一般,*,*,*,かた,カタ,カタ">かた</tok>

<tok id="30" feature="記号,括弧閉,*,*,*,*,」,」,」">」</tok>

<tok id="31" feature="助詞,格助詞,連語,*,*,*,って,ッテ,ッテ">って</tok>

</chunk>

<chunk id="11" link="-1" rel="D" score="0.000000" head="33" func="36">

<tok id="32" feature="名詞,サ変接続,*,*,*,*,超絶,チョウゼツ,チョーゼツ">超絶</tok>

<tok id="33" feature="名詞,形容動詞語幹,*,*,*,*,大事,ダイジ,ダイジ">大事</tok>

<tok id="34" feature="助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ">だ</tok>

<tok id="35" feature="助詞,終助詞,*,*,*,*,よ,ヨ,ヨ">よ</tok>

<tok id="36" feature="助詞,終助詞,*,*,*,*,ね,ネ,ネ">ね</tok>

<tok id="37" feature="記号,句点,*,*,*,*,。,。,。">。</tok>

</chunk>

</sentence>



各chunkに含まれるlinkが下に続くchunk idとの関連を示しています。


実験結果

「クーリエ」<-「おもしろい」という関係が取得出来ました。

ただ、上のコードだと1つの関係性しか取得出来ないため、複数ある場合は更に工夫が必要ですね。。

お手数ですが間違いありましたら、ご指摘いただけますと助かります。