MeCabはunidicなしでも動く。でもそれが一番怖い

MeCabって、unidicが無くても普通に動くんですよね。
インストールしてないのにエラーも出ない。解析結果も一応出る。

…で、何が起きるかというと、「動いてるからOK」と思ってしまう
でも分類(テキスト分類、カテゴリ分け、スパム判定みたいなやつ)に使っていると、ここが一番怖いポイントになります。

なぜなら、辞書が違うのに、静かに結果が変わるからです。

※この記事は「大きなトラブルが起きた話」ではありません。
落ちずに使えていたからこそ、後から気づいた注意点のメモです。

※私の環境では、実際にはunidic-lite が入っておらず、後からpip install unidic-lite で追加しました。
ただし、未インストールの状態でもエラーは出ず、動いてしまっていました。

目次

結論:分類に使うなら、辞書は明示した方が安全

先に結論だけ。

  • MeCabは辞書が無くても落ちません
  • でも「どの辞書で解析しているか」がズレると、前処理がズレます
  • 前処理がズレると、分類モデルの入力が変わります
  • だから精度が落ちたり、環境差で結果が揺れたりします

つまり、分類用途では
「辞書を入れる」より「辞書を指定して固定する」が本質です。

なぜエラーが出ないの?(静かな罠の正体)

MeCabは、ざっくり言うとこういう挙動です。

  • 辞書が見つかれば、その辞書で解析する
  • 見つからなければ、別の辞書(システム辞書など)にフォールバックして解析する
  • どれかで解析できるなら、エラーは出ない

この仕様のおかげで「動く」んですが、逆に言うと…

辞書が違っても、動作上は正常に見える

ここが一番ハマりやすいところです。

分類で困るのは「精度」より「再現性」

分類で苦労するのは、精度が落ちることももちろんですが、それより厄介なのは 再現性が壊れることです。

  • 学習したときはAの辞書
  • 推論(本番)ではBの辞書
  • でも動くから気づかない
  • ある日、急に分類結果が変わったように見える

「同じコードなのに結果が違う」って、原因追うのが本当にしんどいんですよね。
そして犯人が 辞書 だったとき、だいたい静かに心が折れます。

どう変わる?(辞書が違うと特徴量が別物になる)

辞書が変わると、分かち書き結果や品詞の扱いが変わります。

  • どこで単語を区切るか
  • どの品詞として扱うか
  • 原形化(原形・活用)の取り方
  • そもそも辞書に載っている語彙

結果として、TF-IDFやBoW、n-gramなどの入力特徴量が変わり、分類モデルは「別の世界の文章」を読まされることになります。

対策:辞書を明示して「使っている辞書」をログに残す

ここから実務の話です。やることはシンプル。

  1. 辞書を明示して初期化する
  2. 起動時に 辞書のパスや辞書情報をログに出す
  3. もし辞書が見つからないなら 例外にして落とす(静かに進ませない)

「静かに壊れる」を「派手に止める」に変えるのがコツです。

コード(コピペで動くチェック用)

※ライブラリは環境により異なるので、まずは「辞書がどれになっているか」を確認する方向に寄せます。
(python-mecab / fugashi / natto-py など流派があるため、ここでは“考え方”が崩れない形にします)

1) MeCabの辞書が何を使っているか確認(mecabコマンドがある場合)

ターミナルで(これが一番確実):

Bash
mecab -D

dictionary pathfilename が出れば、それが実際に使われている辞書です。
ここが unidicじゃない のに気づけたら勝ち。

2) Python側で辞書を明示する(パス指定の考え方)

MeCabは初期化時にオプションで辞書パスを渡せます。
例(概念として):

Python
import MeCab

DICDIR = "/path/to/unidic/dicdir"  # ← ここを固定する

tagger = MeCab.Tagger(f"-Owakati -d {DICDIR}")
print(tagger.parse("今日はMeCabの辞書チェックをします"))

ポイントはここです:

  • -d で辞書ディレクトリを固定
  • 固定できないなら、検出して表示→期待と違えば落とす

3) “静かに進ませない” ガード(辞書が違ったら例外にする)

「辞書が違うのに解析して進んでしまう」を止めます。

Python
import subprocess
import sys

def get_mecab_dic_info() -> str:
    # mecabコマンドがある前提の最強チェック
    result = subprocess.run(["mecab", "-D"], capture_output=True, text=True)
    if result.returncode != 0:
        raise RuntimeError("mecab -D に失敗しました。MeCabがPATHにあるか確認してください。")
    return result.stdout

def assert_unidic(dic_info: str):
    # “unidic” という文字列が含まれているかで最低限ガード
    if "unidic" not in dic_info.lower():
        raise RuntimeError(
            "MeCabがunidicを使っていない可能性があります。\n"
            "辞書が変わると分類の前処理が変わり、精度・再現性が崩れます。\n"
            "mecab -D の出力を確認し、辞書を明示して固定してください。"
        )

if __name__ == "__main__":
    info = get_mecab_dic_info()
    print(info)  # 起動ログとして残す
    assert_unidic(info)
    print("OK: unidicっぽい辞書が使われています。")
  • 本番では print(info) をログへ
  • これで「環境が違うのに動いてしまう」を止められます

実務で効くチェックリスト(読者が嬉しいやつ)

  • 学習環境で mecab -D を保存している
  • 本番環境でも同じ mecab -D が出る
  • Pythonの初期化時に -d で辞書を固定している
  • 辞書が違うなら例外で止める(静かに進ませない)
  • requirementsだけでなく、辞書も含めた環境差を意識している

まとめ:分類の精度を守るのは「辞書の固定」

MeCabはunidicが無くても動きます。
でも、その“親切さ”が罠になることがあります。

分類で大事なのは「動くこと」より、同じ前処理が再現できること
辞書がズレると、入力がズレる。入力がズレると、結果がズレます。

だから、こうしておくのが安心です。

  • 解析に使う辞書を明示
  • 起動時に辞書情報をログ化
  • 期待と違うなら止める

これだけで「原因が分からない沼」から、かなり抜けやすくなります。

注意
MeCabは辞書が違ってもエラーが出ないため、分類の前処理が変わっていることに気づきにくいです。学習環境と本番環境で mecab -D の結果を揃え、辞書を明示して固定するのがおすすめです。


目次