In [3]:
import pickle
import CaboCha
cabocha = CaboCha.Parser()

第5章: 係り受け解析

夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をCaboChaを使って係り受け解析し,
その結果をneko.txt.cabochaというファイルに保存せよ.
このファイルを用いて,以下の問に対応するプログラムを実装せよ


In [13]:
with open('neko_lattice.txt.cabocha', 'w') as f:
    neko = "".join([i for i in open('neko.txt', 'r')])
    tree = cabocha.parse(neko)
    f.write(tree.toString(CaboCha.FORMAT_LATTICE))

40. 係り受け解析結果(形態素)

形態素を表すクラスMorphを実装せよ.このクラスは表層形(surface),基本形(base),
品詞(pos),品詞細分類1(pos1)をメンバ変数に持つこととする.
さらに,CaboChaの解析結果(neko.txt.cabocha)を読み込み,各文をMorphオブジェクトのリストとして表現し,3文目の形態素列を表示せよ


In [14]:
class Morph(object):
    def __init__(self, _surface, _base, _pos, _pos1):
        self.surface = _surface
        self.base = _base
        self.pos = _pos
        self.pos1 = _pos1


sentence_list = []
object_list = []    
sentences = [i.strip('\n') for i in open('neko_lattice.txt.cabocha') \
             if i[0] not in ('*', ' ')]
sentences = [i.split('\t') for i in sentences if i[0] not in ('EOS')]
surface = [s[0] for s in sentences]
attribute = [s[1].split(',') for s in sentences]

for i, j in zip(surface, attribute):
    object_list.append(Morph(i, j[6], j[0], j[1]))
    if i in ('。'):
        sentence_list.append(object_list)
        object_list = []

str.strip() -> 引数を与えないと言語の空白と\nを抜く

41. 係り受け解析結果の読み込み(文節・係り受け)

40に加えて,文節を表すクラスChunkを実装せよ.
このクラスは形態素(Morphオブジェクト)のリスト(morphs),
係り先文節インデックス番号(dst),係り元文節インデックス番号のリスト(srcs)をメンバ変数に持つこととする.
さらに,入力テキストのCaboChaの解析結果を読み込み,
1文をChunkオブジェクトのリストとして表現し,
8文目の文節の文字列と係り先を表示せよ.
第5章の残りの問題では,ここで作ったプログラムを活用せよ.

  • chunk = 文節
  • chunk/id = 文節番号
  • chunk/link = 係り先の文節番号
  • chunk/rel = (不明)
  • chunk/score = 係り関係のスコア(大きい方が係りやすい)
  • chunk/head = 主辞の形態素番号
  • chunk/func = 機能語の形態素番号
  • tok = 形態素
  • tok/id = 形態素番号
  • tok/feature = 品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
  • tok/値 = 表層形

In [1]:
import xml.etree.ElementTree as ET
class Chunk(object):
    """
    morph: list Morphオブジェクト
    dst: int インデックス番号
    srcs: .list インデックス番号

    """
    def __init__(self, _morphs, _dst, _srcs):
        self.morphs = _morphs
        self.dst = _dst
        self.srcs = _srcs
        
tree = ET.parse('neko_new.xml')
root = tree.getroot()

In [21]:
count = 0
for chunck in root.iter('chunk'):
    count += 1
    print(chunck.items())
    if count == 5:
        break


[('rel', 'D'), ('score', '-0.764522'), ('id', '0'), ('func', '0'), ('link', '2'), ('head', '0')]
[('rel', 'D'), ('score', '-0.764522'), ('id', '1'), ('func', '2'), ('link', '2'), ('head', '1')]
[('rel', 'D'), ('score', '0.000000'), ('id', '2'), ('func', '5'), ('link', '-1'), ('head', '3')]
[('rel', 'D'), ('score', '-1.911675'), ('id', '0'), ('func', '1'), ('link', '2'), ('head', '0')]
[('rel', 'D'), ('score', '-1.911675'), ('id', '1'), ('func', '2'), ('link', '2'), ('head', '2')]

In [39]: