아마추어 언어 처리 100 개 노크 : 38

언어 처리 100개 노크 2015 의 도전 기록입니다. 환경은 Ubuntu 16.04 LTS + Python 3.5.2::Anaconda 4.1.1 (64-bit)입니다. 과거 노크 목록은 여기

제4장: 형태소 해석



나츠메 소세키의 소설 「고배는 고양이이다」의 문장(neko.txt)을 MeCab를 사용해 형태소 해석해, 그 결과를 neko.txt.mecab라는 파일에 보존하라. 이 파일을 사용하여 다음 질문에 해당하는 프로그램을 구현하십시오.

문제 37, 38, 39는 matplotlib 또는 Gnuplot을 사용할 수 있습니다.

38. 히스토그램



단어의 출현 빈도의 히스토그램(가로축에 출현 빈도, 세로축에 출현 빈도를 취하는 단어의 종류수를 막대 그래프로 나타낸 것)를 그릴 수 있다.

완성된 코드:



main.py
# coding: utf-8
import MeCab
from collections import Counter
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

fname = 'neko.txt'
fname_parsed = 'neko.txt.mecab'


def parse_neko():
    '''「吾輩は猫である」を形態素解析
    「吾輩は猫である」(neko.txt)を形態素解析してneko.txt.mecabに保存する
    '''

    with open(fname) as data_file, \
            open(fname_parsed, mode='w') as out_file:

        mecab = MeCab.Tagger()
        out_file.write(mecab.parse(data_file.read()))


def neco_lines():
    '''「吾輩は猫である」の形態素解析結果のジェネレータ
    「吾輩は猫である」の形態素解析結果を順次読み込んで、各形態素を
    ・表層形(surface)
    ・基本形(base)
    ・品詞(pos)
    ・品詞細分類1(pos1)
    の4つをキーとする辞書に格納し、1文ずつ、この辞書のリストとして返す

    戻り値:
    1文の各形態素を辞書化したリスト
    '''
    with open(fname_parsed) as file_parsed:

        morphemes = []
        for line in file_parsed:

            # 表層形はtab区切り、それ以外は','区切りでバラす
            cols = line.split('\t')
            if(len(cols) < 2):
                raise StopIteration     # 区切りがなければ終了
            res_cols = cols[1].split(',')

            # 辞書作成、リストに追加
            morpheme = {
                'surface': cols[0],
                'base': res_cols[6],
                'pos': res_cols[0],
                'pos1': res_cols[1]
            }
            morphemes.append(morpheme)

            # 品詞細分類1が'句点'なら文の終わりと判定
            if res_cols[1] == '句点':
                yield morphemes
                morphemes = []


# 形態素解析
parse_neko()

# Counterオブジェクトに単語をセット
word_counter = Counter()
for line in neco_lines():
    word_counter.update([morpheme['surface'] for morpheme in line])

# 全件取得
list_word = word_counter.most_common()

# 出現数のリスト取得
counts = list(zip(*list_word))[1]

# グラフで使うフォント情報(デフォルトのままでは日本語が表示できない)
fp = FontProperties(
    fname='/usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf'
)

# ヒストグラムのデータ指定
plt.hist(
    counts,             # データのリスト
    bins=20,            # ビンの数
    range=(1, 20))      # 値の範囲

# x軸の値の範囲の調整
plt.xlim(xmin=1, xmax=20)

# グラフのタイトル、ラベル指定
plt.title("38. ヒストグラム", fontproperties=fp)
plt.xlabel('出現頻度', fontproperties=fp)
plt.ylabel('単語の種類数', fontproperties=fp)

# グリッドを表示
plt.grid(axis='y')

# 表示
plt.show()

실행 결과:





히스토그램


parse_neko()neco_lines() , 및 word_counter 를 구하는 곳까지는 전문 와 같습니다.

히스토그램은 스스로 계급별로 집계하지 않고 값의 리스트를 pyplot.hist() 에 건네주는 것만으로 만들어 줍니다. 이것은 편리!

실제로 그래프를 몇 개 작성해 보았습니다만, 대부분의 단어가 출현 빈도는 20 이하인 것을 알았습니다. 따라서 히스토그램의 계급수는 20( bins=20 )로, 또 집계하는 값의 범위도 1에서 20( range=(1,20) )로 하고 있습니다.

앞문과 마찬가지로 x축의 범위는 디폴트라고 출현 빈도 0이 들어가 버려서 공백을 할 수 있으므로 pyplot.xlim() 로 조정했습니다.

 
39번째 노크는 이상입니다. 실수 등이 있으시면 지적해 주시면 감사하겠습니다.

실행 결과에는 100개 노크에서 사용하는 코퍼스 데이터 로 배포된 데이터의 일부가 포함됩니다. 이 4장에서 사용하고 있는 데이터는 푸른 하늘 문고 로 공개되고 있는 나츠메 소세키의 장편 소설 '고배는 고양이이다'가 바탕으로 되어 있습니다.

좋은 웹페이지 즐겨찾기