ぴよまるの雑多な技術所

間違えて休職中ってずっと書いていて心配されていました。全部ちょっとずつ齧って好きって思える技術を見つけたい。研究分野は数理最適化。

Mecabの形態素解析の精度を向上する

形態素解析によく使うMecabですが、何も考えずに使うと変なところで切れてしまうことがあったり、品詞が違ったりしました。今回は米津玄師さんのLemonを題材に、Mecab形態素解析の精度の向上について書きます。

Mecabとは

taku910.github.io 上記を参照してください。形態素解析に用いるエンジンとしては他にChaSen隠れマルコフモデル)やJuman(RNN言語モデル)がありますが、Mecabは高速に動作するため現場でよく使われています。 インストールについても上記の記事を参考にしてください。Macの場合は

#Mecab
brew install mecab
#初期の辞書
brew install mecab mecab-ipadic
#python用のmecab
pip install mecab-python3

で最低限の環境が整うはずです。今回の検証環境は以下です。

mecab -v
#mecab of 0.996
python -V
#Python 3.6.5

歌詞を読み込む

歌詞をテキストファイルで用意します。今回はLemonlemon.txtというファイル名で用意しました。

夢ならばどれほどよかったでしょう
未だにあなたのことを夢にみる
忘れた物を取りに帰るように
古びた思い出の誇りを払う

この歌詞をPythonで読み込みます。 一行ずつlistに入った入れ子のlistになるので、reduceを用いて一行ずつのstrのlistに直します。

import pandas as pd
import numpy as np
import MeCab
from functools import reduce

lyrics = pd.read_table("./lemon.txt", header=None, encoding="utf-8").values.tolist()
lyrics = [reduce(lambda x: x, l) for l in lyrics]
print(lyrics)
#['夢ならばどれほどよかったでしょう', '未だにあなたのことを夢にみる', '忘れた物を取りに帰るように', '古びた思い出の誇りを払う']

辞書なしで形態素解析をする

#辞書なし
tagger = MeCab.Tagger()
no_dict_result = []
for line in lyrics:
    tagger.parse("")
    node = tagger.parseToNode(line)
    while node:
        if node.surface:
            result = "「{}」の品詞は{}".format(node.surface, node.feature.split(",")[0])
            no_dict_result.append(result)
        node = node.next

tagger.parse("")については、入れないとエンコードエラーを起こすことがあります。 詳しくは下記を参照してください。

qiita.com

辞書ありで形態素解析をする

辞書としてmecab-ipadic-neologdを使います。説明は下記を参照してください。

github.com

指示にしたがってインストールしていきます。

git clone --depth 1 https://github.com/neologd/mecab-ipadic-neologd.git
cd mecab-ipadic-neologd
./bin/install-mecab-ipadic-neologd -n

Mecabを使う際に辞書の位置を指定する必要がありますが、下記のコマンドで確認できます。

echo `mecab-config --dicdir`"/mecab-ipadic-neologd"
#辞書あり
tagger_with_dict = MeCab.Tagger('-d /usr/local/lib/mecab/dic/mecab-ipadic-neologd')
use_dict_result = []
for line in lyrics:
    tagger_with_dict.parse("")#エンコードエラーのため(https://qiita.com/kasajei/items/0805b433f363f1dba785)
    node = tagger_with_dict.parseToNode(line)
    while node:
        if node.surface:
            result = "「{}」の品詞は{}".format(node.surface, node.feature.split(",")[0])
            use_dict_result.append(result)
        node = node.next

テキストファイルに書き出して比較する

いままでの結果を下記のようなコードでテキストファイルに書き出して比較してみました。

write_path = "no-dict.txt"
print(no_dict_result)
with open(write_path, mode='w',encoding='utf-8') as f:
    f.write('\n'.join(no_dict_result))

上記は辞書なしで形態素解析をするの方の結果を書き出しています。 結果はこんな感じです。左が辞書なしで形態素解析をするの結果で、右が辞書ありで形態素解析をするの結果です。辞書なしもともとの精度も今回の歌詞については悪くありませんが、「夢ならば」が「夢」「なら」「ば」とわかれるなど、さらに精度が向上していることがわかります。

f:id:let_piyomaru:20200414223138p:plain
形態素解析の結果の比較

まとめ

辞書を使うことでMecab形態素解析の精度を向上できました。 他にも形態素解析前に前処理として記号やタグ文字を取り除くことや、速度を気にしないならJuman++を使うなどの精度向上の方法が考えられます。今回は取り上げませんでしたが、前処理にはneologdnというPythonのライブラリを使うこともできるようです。

今回のソースコードは結果も含めて下記にあげてあります。

github.com