言語処理100本ノック 第4章: 形態素解析 (前編)
はじめに
今回は 言語処理100本ノック 第4章: 形態素解析 の前編です。
これまでの
ohshige.hatenablog.com ohshige.hatenablog.com
第4章: 形態素解析
Python 3.7.0
でやっていきます。
問題の解釈違い、間違い等ありましたら、教えていただけると幸いです。
指定の「吾輩は猫である」のテキストをダウンロードしてneko.txtとして保存し、mecabをインストールした状態で、
cat neko.txt | mecab > neko.txt.mecab
として、neko.txt.mecabを準備した状態です。
30. 形態素解析結果の読み込み
問題
形態素解析結果(neko.txt.mecab)を読み込むプログラムを実装せよ.
ただし,各形態素は表層形(surface),基本形(base),品詞(pos),品詞細分類1(pos1)をキーとするマッピング型に格納し,1文を形態素(マッピング型)のリストとして表現せよ.
第4章の残りの問題では,ここで作ったプログラムを活用せよ.
解答&出力
def get_neko_morphemes(): morphemes_list = [] with open("neko.txt.mecab") as f: morphemes = [] for i, line in enumerate(f): split_line = line.rstrip("\r\n").split("\t") if len(split_line) == 1: if len(morphemes) != 0: morphemes_list.append(morphemes) morphemes = [] continue morpheme_map = split_line[1].split(",") morpheme = { "surface": split_line[0], "base": morpheme_map[6], "pos": morpheme_map[0], "pos1": morpheme_map[1], } morphemes.append(morpheme) else: if len(morphemes) != 0: morphemes_list.append(morphemes) return morphemes_list if __name__ == "__main__": from pprint import pprint result = get_neko_morphemes() pprint(result[:10])
[[{'base': '一', 'pos': '名詞', 'pos1': '数', 'surface': '一'}], [{'base': '\u3000', 'pos': '記号', 'pos1': '空白', 'surface': '\u3000'}, {'base': '吾輩', 'pos': '名詞', 'pos1': '代名詞', 'surface': '吾輩'}, {'base': 'は', 'pos': '助詞', 'pos1': '係助詞', 'surface': 'は'}, {'base': '猫', 'pos': '名詞', 'pos1': '一般', 'surface': '猫'}, {'base': 'だ', 'pos': '助動詞', 'pos1': '*', 'surface': 'で'}, {'base': 'ある', 'pos': '助動詞', 'pos1': '*', 'surface': 'ある'}, {'base': '。', 'pos': '記号', 'pos1': '句点', 'surface': '。'}], 〜 {'base': '感じ', 'pos': '名詞', 'pos1': '一般', 'surface': '感じ'}, {'base': 'が', 'pos': '助詞', 'pos1': '格助詞', 'surface': 'が'}, {'base': 'ある', 'pos': '動詞', 'pos1': '自立', 'surface': 'あっ'}, {'base': 'た', 'pos': '助動詞', 'pos1': '*', 'surface': 'た'}, {'base': 'ばかり', 'pos': '助詞', 'pos1': '副助詞', 'surface': 'ばかり'}, {'base': 'だ', 'pos': '助動詞', 'pos1': '*', 'surface': 'で'}, {'base': 'ある', 'pos': '助動詞', 'pos1': '*', 'surface': 'ある'}, {'base': '。', 'pos': '記号', 'pos1': '句点', 'surface': '。'}]]
ひとこと
1行ずつ読み込み、タブとカンマ(,)で区切って、表層形はタブ区切りの左、品詞はタブ区切りの右のうちのカンマ区切りの1つ目など、mapに入れていくだけです。
結果を全て出力すると大変なので、最初の10件だけを出力しています。(以降、同様)
31. 動詞
問題
動詞の表層形をすべて抽出せよ.
解答&出力
from div04.sec30 import get_neko_morphemes morphemes_list = get_neko_morphemes() result = [] for morphemes in morphemes_list: for morpheme in morphemes: if morpheme["pos"] == "動詞": result.append(morpheme["surface"]) print(result[:10])
['生れ', 'つか', 'し', '泣い', 'し', 'いる', '始め', '見', '聞く', '捕え']
ひとこと
問題30を利用して、ループで回して品詞(pos)が「動詞」であるものの表層系(surface)を結果に格納しているだけです。
32. 動詞の原形
問題
動詞の原形をすべて抽出せよ.
解答&出力
from div04.sec30 import get_neko_morphemes morphemes_list = get_neko_morphemes() result = [] for morphemes in morphemes_list: for morpheme in morphemes: if morpheme["pos"] == "動詞": result.append(morpheme["base"]) print(result[:10])
['生れる', 'つく', 'する', '泣く', 'する', 'いる', '始める', '見る', '聞く', '捕える']
ひとこと
31と同じように、ループで回して品詞(pos)が「動詞」であるものの原形(base)を結果に格納しているだけです。
33. サ変名詞
問題
サ変接続の名詞をすべて抽出せよ.
解答&出力
from div04.sec30 import get_neko_morphemes morphemes_list = get_neko_morphemes() result = [] for morphemes in morphemes_list: for morpheme in morphemes: if morpheme["pos"] == "名詞" and morpheme["pos1"] == "サ変接続": result.append(morpheme["surface"]) print(result[:10])
['見当', '記憶', '話', '装飾', '突起', '運転', '記憶', '分別', '決心', '我慢']
ひとこと
ループで回して、品詞(pos)が「名詞」であり且つ品詞細分類1(pos1)が「サ変接続」であるものを結果に格納しています。
問題に指定はありませんが、表層系を格納しています。
34. 「AのB」
問題
2つの名詞が「の」で連結されている名詞句を抽出せよ.
解答&出力
from div04.sec30 import get_neko_morphemes morphemes_list = get_neko_morphemes() result = [] for morphemes in morphemes_list: for i in range(1, len(morphemes) - 1): if morphemes[i]["surface"] != "の": continue before = morphemes[i - 1] after = morphemes[i + 1] if before["pos"] != "名詞" or after["pos"] != "名詞": continue result.append(before["surface"] + "の" + after["surface"]) print(result[:10])
['彼の掌', '掌の上', '書生の顔', 'はずの顔', '顔の真中', '穴の中', '書生の掌', '掌の裏', '何の事', '肝心の母親']
ひとこと
「の」を探した上で、その前後が「名詞」であるものを抽出しています。
連続した3つの形態素を抽出することになるので、「の」探索の範囲(range(1, len(morphemes) - 1)
)は最初と最後を除いています。
おわりに
3章は難しかったですが、4章の少なくとも前半は割りと簡単でした。
mecabもbrewなどで簡単にインストールできるので、形態素解析に入門するのも簡単なご時世です。
続き
まだ