2018年04月12日

言語処理100本ノックでPython入門 #35 - 名詞の連接

  
言語処理100本ノック 2015の問題35に挑戦です。

■ 問題
夏目漱石の小説『吾輩は猫である』の文章(neko.txt)をMeCabを使って形態素解析し,その結果をneko.txt.mecabというファイルに保存せよ.このファイルを用いて,以下の問に対応するプログラムを実装せよ. なお,問題37, 38, 39はmatplotlibもしくはGnuplotを用いるとよい.

35. 名詞の連接
名詞の連接(連続して出現する名詞)を最長一致で抽出せよ.

■ Pythonのコード
import re

def analyze():
    lines = []
    sentence = []
    with open('neko.txt.mecab', 'r', encoding='utf8') as fin:
        for line in fin:
            words = re.split(r'\t|,|\n', line)
            if words[0] == 'EOS':
                if sentence:
                    lines.append(sentence)
                    sentence = []
                continue
            sentence.append({
                "surface": words[0],
                "base": words[7],
                "pos": words[1],
                "pos1": words[2],
            })
    return lines

def extractContinuousNouns(lines):
    for sentense in lines:
        noun = ''
        count = 0
        for word in sentense:
            if word['pos'] == '名詞' and (noun != '' or word['pos1'] != '副詞可能'):
                noun += word['surface']
                count += 1
            else:
                if count > 1:
                    yield noun
                noun = ''
                count = 0

def main():
    article = analyze()
    nouns = [surface for surface in extractContinuousNouns(article)]
    print(nouns)

if __name__ == '__main__':
    main()

■ ちょっと説明

単純に名詞の連続だと
'その後猫'  'この間おさん'  '自ら筆'  '元来放蕩家' 
などちょっとおかしな単語も引っ張ってきてしまっているので、連続した名詞の先頭のpos1が副詞可能な場合を除外してみました。

しかし、そうすると、 '前後不覚'  'ふだん着' などいくつか除外してほしくない単語も除外されてしまいました。 まあどっちもどっちですね。

この精度を高めようとすると、辞書登録をするしかないですかね。
それとも、pos2の内容もみて条件判定をするといった泥臭いコードを書く必要があるのでしょうか。

それと、ひさしぶりに if else 使いました。elseにの後ろにも:付けるんだった。すっかり忘れていました。


■ 結果

結果の先頭部分を載せます。
['人間中', '時妙', '一毛', '一度', 'ぷうぷうと煙', '邸内', '三毛', '書生以外', '四五遍', '三馬', '御台所', 'まま奥', '住家', '勉強家', '勉強家', '勤勉家', '二三ページ', '主人以外', '限り吾輩', '二人', '一つ床', '一人', '最後大変', '——猫', '神経胃弱性', '物指', '尻ぺたをひどく', '言語同断',
あまり良い結果とは言えないです。

「ぶうぶうと煙」は、どう考えても名詞の連結とは言えないよなー。