grasys blog

Mecab を試してみた

はじめに

こんにちは。2023 年 9 月に grasys に入社したミャンマー出身のスースーです。grasys に入社してからは、これまで自分が触ったことのなかった新しい技術を色々触ることが出来ました。今回はその中の一つである MeCab について説明します。

現在 AI は有名になりましたよね。AI モデル、特にテキスト分類、感情分析、翻訳などのモデルでは、テキストをトークン化するか、意味のある単位に分割する必要があります。MeCab は、単語間にスペースがない日本語テキストのトークン化に優れており、AI モデルを強化できる形態情報を提供します。

形態素解析

国によって色々な言語があります。それら言語に合わせて様々な形態素解析があります。

なぜ形態素解析は必要なのでしょうか?

AI は人が書いた様々な文章を検索しています。そして、検索した文章をシステムで分析しています。入力された文章を単語や形態素に分割し、それぞれの品詞や基本形、読み仮名などを解析します。この分析をするために形態素解析が必要になりました。

例:英語文章

My name is Su Su.

これを形態素解析すると「My name、is、Su Su、.」になります。英語の文章にはスペースがあります。スペースがあるので形態素解析は日本語より簡単になります。

日本語の文章にはスペースがありません。日本語ではどのような形態素解析になるでしょうか?

例:日本語文章

私の名前はスースーです。

この文章を形態素解析すると「私、の、名前、は、スースー、です、 。」になります。日本語の形態素解析には色々なモデルがあります。そのモデルの一つ、Mecab についてこれから説明します。

Mecab とは?

MeCab は、日本語のテキストを処理および分析するために設計されたオープンソースの形態素解析ツールです。これは、単語間にスペースがなく、複雑な文法構造を持つ日本語を扱う場合に特に役立つ、自然言語処理(NLP)タスクに使用される強力なツールです。

Mecab は Python や Java、C 言語で使えるので利用しやすいです。

Mecab を選んだ理由

日本語形態素解析は下記のように様々な種類があります。

  • Mecab
  • Nagisa
  • SentencePiece
  • Sudachi
  • Kuromoji
  • Juman++
  • Yahoo! 形態素解析 API

私は、この中から Mecab、Nagisa、SentencePiece で比較検討しました。

Nagisa は形態素解析で言葉を取得するのは簡単だったのですが、新しく言葉を追加するのは難しい印象がありました。

SentencePiece も実際にテストしてみたのですが、Nagisa と同様に言葉の追加など難しかったです。

簡単に言葉を追加できること、使い勝手が良いことなどの観点から、私は Mecab を選びました。

Mecab の良い点

私は、Mecab の以下の点が良いなと思っています。

  • 新しい言葉を簡単に追加出来る
  • Python、Java、C++、Ruby、Go で利用出来る
  • オープンソースソフトウェアなので無料で利用出来る
  • ソースコードを柔軟にカスタマイズできる

Mecab のインストール方法

私は google vm instance の linux debian を使っているので、下記は linux debian でインストールする方法です。

Mecab の ipa 辞書へ新しく言葉を追加したいので mecab-0.996 と mecab ipa の二つをダウンロードしてインストールします。

mkdir mecab_source
cd mecab_source

#ソースコードをダウンロードして解凍、移動
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7cENtOXlicTFaRUE' -O mecab-0.996.tar.gz

tar zxvf mecab-0.996.tar.gz && rm mecab-0.996.tar.gz
cd mecab-0.996

#インストールフォルダーを作成する
sudo mkdir -p /opt/mecab

# configure(コンパイルのための設定)、コンパイル、インストールを実行
./configure --prefix=/opt/mecab --with-charset=utf8 --enable-utf8-only
make
sudo make install
#環境変数を設定
echo "export PATH=/opt/mecab/bin:\$PATH" >> ~/.bashrc
source ~/.bashrc
#mecab-0.996 フォルダーから出る
cd ..

# mecab ipa のソースコードをダウンロードして解凍、移動
wget 'https://drive.google.com/uc?export=download&id=0B4y35FiV1wh7MWVlSDBCSXZMTXM' -O $mecab_ipa_name.tar.gz
tar zxvf $mecab_ipa_name.tar.gz && rm $mecab_ipa_name.tar.gz
cd $mecab_ipa_name

#configure(コンパイルのための設定)、コンパイル、インストールを実行
./configure --with-mecab-config=/opt/mecab/bin/mecab-config --with-charset=utf8
make
sudo make install

インストールした Mecab が実際にインストールされて動いているかを確認します。

下記のコマンドを実行します。

echo "私の名前はスースーです" | mecab

下記のような結果を見られます。

私    名詞
の    動詞
名前   名詞
は    動詞
スースー 名詞
です   助動詞

Mecab は想定通り動いているようです。

Python で Mecab に新しい言葉を追加する方法

Mecab へ新しく言葉を追加する方法は二つあります。

  • システム辞書への追加
  • ユーザ辞書への追加

Mecab ドキュメントを見ると、システム辞書への追加の方がユーザ辞書へ追加するよりも解析する速度が早いとのことだったので、今回はシステム辞書へ追加する方法で新しい言葉を追加します。

まずは csv ファイルを作成します。Mecab の辞書で使う csv ファイルのカラムは 13 列あります。

この 13 列で新しい言葉を追加します。

表層形、左文脈ID、右文脈ID、コスト、品詞、品詞細分類1、品詞細分類2、品詞細分類3、活用型、活用形、原形、読み、発音

Mecab では通常、「旅行団体」という言葉は「旅行 名詞、団体 名詞」と二つの言葉で形態素解析されます。この言葉を「旅行団体 名詞」と一つの言葉になるように新しく言葉を追加してみます。

「旅行団体」と合わせて「企業組織」、「学生集団」、「同僚の仲間」、「プロジェクトチーム」の言葉も一つとして認識されるように辞書へ追加します。

下記のコマンドを実行します。

echo "旅行団体" | mecab
echo "企業組織" | mecab
echo "学生集団" | mecab
echo "同僚の仲間" | mecab
echo "プロジェクトチーム" | mecab

こちらのキャプチャは辞書へ追加する前の状態です。それぞれ複数の言葉に分けられていることがわかります。

新しい言葉を csv ファイルで作成するのに、言葉 1 個、2 個程度であれば一つ一つ作成するので問題ないですが、追加したい言葉が 100 個ですとかそれ以上ある場合は限界があります。

そこで、今回は python で csv ファイルを作成してみます。

下記のコマンドを実行します。

mkdir mecab_blog
cd mecab_blog
rye init . --min-py 3.11 --no-pin --private --virtual
rye sync
touch new_word.py

Mecab の辞書に入れたい言葉を excel ファイルに入れます。

例:new_word.xlsx ファイルに下記のように言葉を記入します。

new_word.py のファイルに下記のコードを入れてください。left_context_id と right_context_id を固定で 1285 と cost を-3150 で固定で入れます。この固定の left_context_id、right_context_id、cost についてはまたの機会に詳しく説明できればと思います。

import pandas as pd
import typer
import pykakasi
app = typer.Typer()

@app.command()
def main():
    df = pd.read_excel(r"../new_word.xlsx",sheet_name=['new_word'])
    df = pd.concat(df, axis=0, ignore_index=True)
    data_list = []
    for index, row in df.iterrows():
        print(row['word'])
        #漢字とひらがなをカタカナに変更するため pykakasi を使用
        kks = pykakasi.kakasi()
        japan_word_convert = kks.convert(row['word'])
        japan_word_kana =  ''.join([entry['kana'] for entry in japan_word_convert])
        #mecab の 13 列に言葉を追加
        data_list.append(
            {
                'word': row['word'],
                'left_context_id': 1285,
                'right_context_id': 1285,
                'cost': -3150,
                'speech': "名詞",
                'subclassification_1': "*",
                'subclassification_2': "*",
                'subclassification_3': "*",
                'utilization_type': "*",
                'conjugation_form': "*",
                'original_form': row['word'],
                'reading': japan_word_kana,
                'pronunciation': japan_word_kana,
            }
        )
    pd_data = pd.DataFrame(data_list)

    if not pd_data.empty:
        pd_data.to_csv('new_word.csv', index=False, header=None)
    else:
        print("DataFrame is empty.")

    print("count data",len(pd_data))

if __name__ == "__main__":
    app()
rye add pandas
rye add typer
rye add pykakasi
rye add openpyxl

python script を実行して csv ファイルを出力します。

rye run python new_word.py

python ファイルを実行すると、このような csv ファイルが出力されます。

nant@research2:~/mecab_blog$ cat new_word.csv
旅行団体,1285,1285,-3150,名詞,*,*,*,*,*,旅行団体,リョコウダンカラダ,リョコウダンカラダ
企業組織,1285,1285,-3150,名詞,*,*,*,*,*,企業組織,キギョウソシキ,キギョウソシキ
学生集団,1285,1285,-3150,名詞,*,*,*,*,*,学生集団,ガクセイシュウダン,ガクセイシュウダン
同僚の仲間,1285,1285,-3150,名詞,*,*,*,*,*,同僚の仲間,ドウリョウノナカマ,ドウリョウノナカマ
サッカーチーム,1285,1285,-3150,名詞,*,*,*,*,*,サッカーチーム,サッカーチーム,サッカーチーム
趣味の仲間,1285,1285,-3150,名詞,*,*,*,*,*,趣味の仲間,シュミノナカマ,シュミノナカマ

この csv ファイルを Mecab の ipa 辞書へ入れます。

Mecab ipa は EUC で動いているので、さきほどの csv ファイルを UTF8 から EUC に変更します。

下記のコマンドを実行します。

iconv -f UTF-8 -t EUC-JP -o new_word_euc.csv new_word.csv

new_word_euc.csv の EUC ファイルを出力します。

この EUC ファイルを、先ほど作成した mecab_source の中にある mecab-ipadic-2.7.0-20070801 へ入れます。

nant@research2:~/mecab_source/mecab-ipadic-2.7.0-20070801$ ls
AUTHORS          Filler.csv        Noun.adverbal.csv  Noun.place.csv   RESULT        config.log     left-id.def       right-id.def
Adj.csv          INSTALL           Noun.csv           Noun.proper.csv  Suffix.csv    config.status  matrix.bin        sys.dic
Adnominal.csv    Interjection.csv  Noun.demonst.csv   Noun.verbal.csv  Symbol.csv    config.sub     matrix.def        unk.def
Adverb.csv       Makefile          Noun.nai.csv       Others.csv       Verb.csv      configure      missing           unk.dic
Auxil.csv        Makefile.am       Noun.name.csv      Postp-col.csv    aclocal.m4    configure.in   mkinstalldirs
COPYING          Makefile.in       Noun.number.csv    Postp.csv        char.bin      dicrc          new_word_euc.csv
ChangeLog        NEWS              Noun.org.csv       Prefix.csv       char.def      feature.def    pos-id.def
Conjunction.csv  Noun.adjv.csv     Noun.others.csv    README           config.guess  install-sh     rewrite.def

new_word_euc.csv ファイルを mecab-ipadic-2.7.0-20070801 へ入れた後に Mecab ipa 辞書を再度実行します。

下記のコマンドを実行します。

sudo $(mecab-config --libexecdir)/mecab-dict-index -f euc-jp -t utf8

ターミナルで以下のように見られます。先ほどの new_word_euc.csv ファイルが入っていることがわかります。

nant@research2:~/mecab_source/mecab-ipadic-2.7.0-20070801$ sudo $(mecab-config --libexecdir)/mecab-dict-index -f euc-jp -t utf8
reading ./unk.def ... 40
emitting double-array: 100% |###########################################|
./model.def is not found. skipped.
reading ./Auxil.csv ... 199

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

reading ./new_word_euc.csv ... 6

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

reading ./Noun.demonst.csv ... 120
emitting double-array: 100% |###########################################|
reading ./matrix.def ... 1316x1316
emitting matrix      : 100% |###########################################|

done!

Mecab ipa で新しい言葉を csv ファイルで追加した後に、再度 Mecab ipa をインストールします。

下記のコマンドを実行します。

sudo make install

新しい言葉を追加する前に Mecab を実行したら「旅行団体』は二つの言葉になります。以下のような実行結果になります。

新しい言葉を追加してから Mecab を実行すると一つの言葉として認識されました。以下のような結果になります。

Mecab 辞書の csv ファイルにカラムを追加する方法

Mecab の辞書の csv ファイルには 13 のカラムがありますが、さらに追加することも出来ます。

ここでは、13 列から 15 列へ増やしてみます。

new_word_flag 列と remark の列を追加します。

new_word.py ファイルへ下記のコードを入れてください。

import pandas as pd
import typer
import pykakasi
app = typer.Typer()

@app.command()
def main():
    df = pd.read_excel(r"../new_word.xlsx",sheet_name=['new_word'])
    df = pd.concat(df, axis=0, ignore_index=True)
    data_list = []
    for index, row in df.iterrows():
        print(row['word'])
        #漢字とひらがなをカタカナに変更するため pykakasi を使用
        kks = pykakasi.kakasi()
        japan_word_convert = kks.convert(row['word'])
        japan_word_kana =  ''.join([entry['kana'] for entry in japan_word_convert])
        #mecab の 13 列に新規言葉と新規列追加
        data_list.append(
            {
                'word': row['word'],
                'left_context_id': 1285,
                'right_context_id': 1285,
                'cost': -3150,
                'speech': "名詞",
                'subclassification_1': "*",
                'subclassification_2': "*",
                'subclassification_3': "*",
                'utilization_type': "*",
                'conjugation_form': "*",
                'original_form': row['word'],
                'reading': japan_word_kana,
                'pronunciation': japan_word_kana,
                'new_word_flag': 1,
                'remark':"新しい単語",
            }
        )
    pd_data = pd.DataFrame(data_list)

    if not pd_data.empty:
        pd_data.to_csv('new_word.csv', index=False, header=None)
    else:
        print("DataFrame is empty. Nothing to write to the database.")

    print("count data",len(pd_data))

if __name__ == "__main__":
    app()

以下のコマンドを実行します。

rye run python new_word.py

新しい言葉を追加する時と同じコマンドを再度実行します。

python script で実行して出力された csv ファイルは UTF-8 なので、下記のコマンドで EUC に変更します。

iconv -f UTF-8 -t EUC-JP -o new_word_euc.csv new_word.csv

EUC で変更した new_word_euc.csv ファイルを mecab-ipadic-2.7.0-20070801 へ入れた後に、Mecab ipa 辞書を再度実行してインストールします。

下記のコマンドを実行します。

sudo $(mecab-config --libexecdir)/mecab-dict-index -f euc-jp -t utf8
sudo make install

こちらは二列を追加する前の結果です。

二列を追加した後、追加した列の ‘new_word_flag’: 1 と ‘remark’:” 新しい単語” も表示されました。

下記のコマンドを実行します。

echo "年末年始祝日にチームのメンバーと一緒に旅行団体で行きますか?" | mecab

先ほど追加した「旅行団体」の言葉には列も追加しているので ‘new_word_flag’: 1、’remark’:”新しい単語” の項目も表示されています。

それ以外の言葉については、Mecab の基本データのまま表示されていることがわかります。

Mecab 参照リンク https://taku910.github.io/mecab/dic.html

まとめ

今回のブログではこちらの内容について書いてきました。

  • Mecab のインストール方法
  • Mecab のシステム辞書へ言葉を追加する方法
  • Mecab のシステム辞書へ列を追加する方法

続編として、Mecab と Qdrant の連携方法をまとめています。以下のようなことをまとめているので、気になった方はぜひご覧ください。

  • 追加した言葉と追加した列がどのように使われているかを確認する
  • 新しい言葉を Mecab で取得して、ベクトルデータベースで検索する方法

Mecab に関する情報はまだまだ少ないので、この記事が Mecab を学んでる人の助けになれば嬉しいです。

最後に

この他にも、Qdrant(ベクトルデータベース)についてのブログも書いているので、興味のある方はぜひこちらもご覧ください。


採用情報
お問い合わせ