ふくふくHukuhuku Inc.
EP.14Prep 9分公開: 2026-05-10

テキスト前処理:トークナイズ・正規化・ストップワード

形態素解析、ストップワード除去、n-gram、Lemmatization。日本語固有の難しさ(MeCab / SudachiPy / Janome)と、llm 時代の変化。

#テキスト#形態素解析
CO📔 Google Colab で開く(上から順にセルを実行)
シェア

日本語テキスト処理は、単語境界が明示的でない点で英語より難しい。本記事では形態素解析ツール 3 種の比較と、 時代の前処理事情を扱います。

形態素解析ツール比較

ツール特徴速度辞書
MeCab業界標準、C++ 実装最速IPA 辞書 / NEologd
SudachiPyワークス徳島大共同、新語に強い速いSudachi 辞書(高品質)
JanomePure Python、インストール容易遅いIPA 辞書
Ginza (spaCy 連携)依存解析・固有表現もSudachi

ストップワード

  • 自動生成:頻出語の上位 100 を機械的に除外
  • 手動:「です・ます・の・と・が」などをリスト化(slothlib が定番)
  • ドメイン特化:業界用語の頻出語を追加

LLM 時代の変化

LLM の前処理は最小限で OK

/ GPT-4 は前処理にかなり頑健。形態素解析・ストップワード除去なしで投げても、性能は落ちないことが多い。前処理を頑張るのは古典的 (TF-IDF + ロジ回 等)の場合。LLM では「クリーニングしすぎない」のも一つの作法。

Python 実装:MeCab vs SudachiPy 比較

MeCab で形態素解析
Python
# !pip install mecab-python3 unidic-liteimport MeCab
tagger = MeCab.Tagger("-Owakati")  # 分かち書きtext = "今日は良い天気ですね。データエンジニアリングが楽しい。"print(tagger.parse(text).strip())# → 今日 は 良い 天気 です ね 。 データ エンジニアリング が 楽しい 。
# 詳細解析(品詞付き)tagger = MeCab.Tagger()node = tagger.parseToNode(text)while node:    if node.surface:        features = node.feature.split(",")        print(f"{node.surface:15s} {features[0]:10s} {features[6] if len(features)>6 else '*'}")    node = node.next
SudachiPy で形態素解析(より新語に強い)
Python
# !pip install sudachipy sudachidict_corefrom sudachipy import dictionary, tokenizer
tokenizer_obj = dictionary.Dictionary().create()mode = tokenizer.Tokenizer.SplitMode.C  # A=最小, B=中, C=最大
text = "デジタルトランスフォーメーションを推進する"tokens = tokenizer_obj.tokenize(text, mode)for t in tokens:    print(f"{t.surface():20s} 品詞:{t.part_of_speech()[0]:10s} 正規:{t.normalized_form()}")
ストップワード除去 + n-gram 抽出
Python
import re
# slothlib 互換のストップワードリストSTOPWORDS = {    "の", "に", "は", "を", "た", "が", "で", "て", "と", "し", "れ", "さ",    "ある", "いる", "も", "する", "から", "な", "こと", "として", "い", "や",    "れる", "など", "なっ", "ない", "この", "ため", "その", "あっ", "よう",    "また", "もの", "という", "あり", "まで",}
def filter_tokens(tokens: list, stopwords=STOPWORDS) -> list:    return [t for t in tokens if t not in stopwords and len(t) > 1]
def extract_ngrams(tokens: list, n: int = 2) -> list:    return [" ".join(tokens[i:i+n]) for i in range(len(tokens) - n + 1)]
text = "今日は良い天気ですね。データエンジニアリングが楽しい。"tokens = tagger.parse(text).strip().split()filtered = filter_tokens(tokens)bigrams = extract_ngrams(filtered, 2)print("単語:", filtered)print("Bigram:", bigrams)
TF-IDF ベクトル化
Python
from sklearn.feature_extraction.text import TfidfVectorizer
corpus = [    "データエンジニアリングが楽しい",    "データ基盤を構築する",    "AIを業務に活用する",]
# 単純な空白区切りで投入(事前に分かち書き済み)def tokenize_jp(text):    return tagger.parse(text).strip().split()
vec = TfidfVectorizer(tokenizer=tokenize_jp, token_pattern=None, min_df=1)matrix = vec.fit_transform(corpus)print(vec.get_feature_names_out())print(matrix.toarray())

ふくふくの進め方

構築・分類モデル開発でのテキスト前処理を、ユースケースに応じて最適化します。

次回予告

EP.15 は前処理パイプラインの再現性。本編の到達点として、ここまでの個別技術を1本のパイプラインに束ねます。

シェア

この記事の感想を教えてください

あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。

シリーズの外も探す:

まずは、現状を聞かせてください。

要件が固まっていなくて大丈夫です。現状診断と方針提案までを無料でお手伝いします。

無料相談フォームへ hello [at] hukuhuku [dot] co [dot] jp