Port 53

明日のための技術メモ

言語処理100本ノック 2020 第5章 前半

nlp100.github.io

第5章 係り受け解析の前半(40-44まで)解説書きます。
MeCabに続き、CaboChaとクラスとお友達になる章。
勉強会の準備などで解けていなかったけれど、やっと再開。

第5章 後半はこちら

目次

準備

CaboChaのインストール

$ brew install cabocha
$ brew install crf++

github.com

github.com

この章で使うファイル

cabocha -f1 ai.ja.txt  > ai.ja.txt.parsed

できたファイルは以下の通り。
オプションがないとtree形式で出てきて加工つらそうだったので、
-f1でlattice形式にした。

* 0 -1D 1/1 0.000000
人工  名詞,一般,*,*,*,*,人工,ジンコウ,ジンコー
知能  名詞,一般,*,*,*,*,知能,チノウ,チノー
EOS
EOS
* 0 17D 1/1 0.388993
人工  名詞,一般,*,*,*,*,人工,ジンコウ,ジンコー
知能  名詞,一般,*,*,*,*,知能,チノウ,チノー
* 1 17D 2/3 0.613549
( 記号,括弧開,*,*,*,*,(,(,(
じん  名詞,一般,*,*,*,*,じん,ジン,ジン
こうち   名詞,一般,*,*,*,*,こうち,コウチ,コーチ
のう  助詞,終助詞,*,*,*,*,のう,ノウ,ノー
、 記号,読点,*,*,*,*,、,、,、
、 記号,読点,*,*,*,*,、,、,、

参考

qiita.com

qiita.com

40. 係り受け解析結果の読み込み(形態素

f:id:saturn-glave:20200712140851p:plain

Classあまり書いてこなかったのもあり時間かかってしまった。
ファイルをよく見ると、EOSや空白行、*から始まる行など特殊な場合がある。
そういったパターンは事前に除外する必要がある。

ポイント

  • クラスのインスタンス変数について、中身を見る時はvars()を使う
    • 普通にprintすると、オブジェクトのアドレスが表示される

解答

# coding:utf-8
class Morph:
    def __init__(self, mp):
        self.surface = mp['surface']
        self.base = mp['base']
        self.pos = mp['pos']
        self.pos1 = mp['pos1']


def CabochaParser():
    path = 'ai.ja.txt.parsed'
    cabocha = []

    with open(path) as f:
        for line in f:
            tmp_line = line.split('EOS\n')
            tmp_line = list(filter(lambda x: x != '', tmp_line))
            # print(tmp_line)
            for item in tmp_line:
                # print(item)
                if item == '' or item[0] == '*':
                    continue
                (surface, attr) = item.split('\t')
                attr = attr.split(',')
                # print(surface, attr)
                attr_dic = {
                    'surface': surface,
                    'base': attr[6],
                    'pos': attr[0],
                    'pos1': attr[1]
                }
                cabocha.append(Morph(attr_dic))
    return cabocha


def main():
    res = CabochaParser()
    # Morphクラスのインスタンス変数がほしいので、varsで取り出す
    for i in res:
        print(vars(i))


if __name__ == "__main__":
    main()

参考

qiita.com

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

f:id:saturn-glave:20200712141006p:plain

42. 係り元と係り先の文節の表示

f:id:saturn-glave:20200712141217p:plain

43. 名詞を含む文節が動詞を含む文節に係るものを抽出

f:id:saturn-glave:20200712141234p:plain

44. 係り受け木の可視化

f:id:saturn-glave:20200712141253p:plain