STEP 2:テキスト前処理の基礎

🔧 STEP 2: テキスト前処理の基礎

クリーニング、トークン化、正規化など、NLPの基礎となる前処理技術を習得します

📋 このステップで学ぶこと

  • テキストクリーニング(小文字化、句読点除去、HTML/URL除去)
  • トークン化(単語、文、サブワード)
  • ストップワードの除去
  • ステミング(Stemming)とレマ化(Lemmatization)
  • NLTKとspaCyの実装

練習問題: 5問

💻 実行環境について

このステップのコードはGoogle Colabで実行できます。
Colabなら環境構築不要で、すぐにコードを試せます。
https://colab.research.google.com/ にアクセスして、新しいノートブックを作成してください。

🎯 1. テキスト前処理とは?

NLPでは、テキストデータをそのままモデルに投入することはできません。 まず「前処理(Preprocessing)」を行い、データを整える必要があります。

1-1. なぜ前処理が必要なのか?

生のテキストデータには、分析に不要な情報がたくさん含まれています。 これらを取り除き、コンピュータが処理しやすい形に変換するのが前処理です。

🍳 料理に例えると…

料理をする前に「下ごしらえ」をするように、NLPでも「前処理」を行います。

【生の食材(生テキスト)】 “こんにちは!!!今日はいい天気ですね😊 https://example.com” ↓ 下ごしらえ(前処理) 【調理できる状態(処理済みテキスト)】 [“こんにちは”, “今日”, “いい”, “天気”]

前処理で行うこと:

■ 絵文字「😊」を削除 ■ URL「https://example.com」を削除 ■ 過剰な句読点「!!!」を整理 ■ テキストを単語に分割 ■ 不要な単語(「は」「ですね」など)を除去

1-2. 前処理を怠るとどうなる?

⚠️ 前処理なしで発生する問題

前処理をしないと、以下の問題が発生します:

【問題1:ノイズが多すぎる】 HTMLタグや絵文字がモデルを混乱させる → 「<div>Hello</div>」の「<div>」は意味がない 【問題2:同じ意味の単語が別物として扱われる】 「走る」「走った」「走って」が全て別の単語に → 語彙数が爆発的に増える 【問題3:計算量が膨大になる】 不要な単語まで処理するため、時間とメモリを浪費

1-3. 前処理の4つの目的

💡 前処理で達成したいこと
  • ① ノイズ除去:HTMLタグ、URL、絵文字など不要な情報を削除
  • ② 正規化:「Hello」と「hello」を同じ単語として扱う
  • ③ 標準化:「走る」「走った」を基本形「走る」に統一
  • ④ 次元削減:「は」「が」「を」など重要でない単語を削除

1-4. 前処理のパイプライン(処理の流れ)

前処理は通常、以下の順序で行います:

【一般的な前処理パイプライン】 生テキスト ↓ ① テキストクリーニング(HTML除去、小文字化など) ↓ ② トークン化(単語に分割) ↓ ③ ストップワード除去(不要な単語を削除) ↓ ④ ステミング/レマ化(基本形に変換) ↓ 処理済みテキスト(モデルに投入可能)
📝 このステップで学ぶ内容

上記のパイプラインの各ステップを、順番に詳しく学んでいきます。

🧹 2. テキストクリーニング

テキストクリーニングは、不要な文字や記号を取り除く作業です。 前処理の最初のステップとして行います。

2-1. 小文字化(Lowercasing)

📝 小文字化とは?

大文字をすべて小文字に変換することです。 これにより、「Hello」と「hello」を同じ単語として扱えます。

なぜ小文字化が必要か?

【問題】大文字・小文字が違うだけで別の単語として扱われる “Hello” → 単語ID: 1 “HELLO” → 単語ID: 2 “hello” → 単語ID: 3 → 同じ意味なのに3つの異なる単語として扱われてしまう! 【解決】小文字化で統一 “Hello” → “hello” → 単語ID: 1 “HELLO” → “hello” → 単語ID: 1 “hello” → “hello” → 単語ID: 1 → すべて同じ単語として扱える!

Pythonでの実装

Pythonには文字列を小文字に変換する lower() メソッドがあります。

# 小文字化のコード # lower()メソッド:文字列のすべての文字を小文字に変換する text = “Hello World! This is NLP.” cleaned_text = text.lower() print(cleaned_text)
実行結果: hello world! this is nlp.
⚠️ 小文字化の注意点

固有名詞など、大文字が意味を持つ場合は注意が必要です:

  • “US”(アメリカ合衆国)→ “us”(私たち)に変わってしまう
  • “Apple”(企業名)→ “apple”(果物)に変わってしまう
  • “IT”(情報技術)→ “it”(それ)に変わってしまう

タスクによっては小文字化しない方が良い場合もあります。

2-2. 句読点の除去

📝 句読点除去とは?

ピリオド、カンマ、感嘆符などの記号を削除することです。 これらは通常、テキストの意味分析には不要です。

【句読点の例】 ! ” # $ % & ‘ ( ) * + , – . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ 【変換例】 “Hello, world! How are you?” → “Hello world How are you”

Pythonでの実装

Pythonの string モジュールには、すべての句読点が定義された punctuation があります。

# 句読点除去のコード import string # stringモジュールをインポート text = “Hello, world! How are you?” # string.punctuation には全ての句読点が含まれている # → !”#$%&'()*+,-./:;<=>?@[\]^_`{|}~ print(“句読点一覧:”, string.punctuation) # translate()メソッドで句読点を削除 # str.maketrans(”, ”, string.punctuation) で # 「句読点を空文字に置き換える」変換テーブルを作成 cleaned_text = text.translate(str.maketrans(”, ”, string.punctuation)) print(“除去後:”, cleaned_text)
実行結果: 句読点一覧: !”#$%&'()*+,-./:;<=>?@[\]^_`{|}~ 除去後: Hello world How are you
💡 コードの解説
  • import string:Pythonの標準ライブラリをインポート
  • string.punctuation:すべての句読点を含む文字列
  • str.maketrans('', '', 削除したい文字):文字を削除する変換テーブルを作成
  • translate():変換テーブルに従って文字を変換

2-3. 数字の処理

📝 数字をどう扱うか?

数字の処理方法は3つあります。タスクによって使い分けます。

【選択肢1:削除する】 “I have 3 apples” → “I have apples” 使う場面:数字が意味を持たない場合 【選択肢2:特殊トークンに置換する】 “I have 3 apples” → “I have <NUM> apples” 使う場面:数字があることは重要だが、具体的な値は不要な場合 【選択肢3:そのまま残す】 “I have 3 apples” → “I have 3 apples” 使う場面:数字の具体的な値が重要な場合(価格分析など)

Pythonでの実装(正規表現を使用)

数字の処理には正規表現(Regular Expression)を使います。 正規表現とは、文字列のパターンを記述するための特殊な記法です。

# 数字処理のコード import re # 正規表現モジュールをインポート text = “I have 3 apples and 5 oranges in 2024.” # 【方法1】数字を削除する # re.sub(パターン, 置換文字, 対象文字列) # \d+ は「1文字以上の数字」を意味する正規表現 cleaned = re.sub(r’\d+’, ”, text) print(“数字削除:”, cleaned) # 【方法2】数字を<NUM>に置換する cleaned = re.sub(r’\d+’, ‘<NUM>’, text) print(“NUM置換:”, cleaned)
実行結果: 数字削除: I have apples and oranges in . NUM置換: I have <NUM> apples and <NUM> oranges in <NUM>.
💡 正規表現の基礎
  • \d:数字1文字にマッチ(0-9)
  • +:直前のパターンが1回以上繰り返す
  • \d+:1文字以上の連続した数字にマッチ
  • r'\d+':先頭の r は「raw文字列」を意味し、バックスラッシュをそのまま扱う

2-4. HTML/URLの除去

📝 なぜHTML/URLを除去するのか?

Webからスクレイピングしたテキストには、HTMLタグやURLが含まれています。 これらは分析には不要なノイズです。

【HTMLタグの例】 “Visit <a href=’https://example.com’>our website</a>!” → タグを除去 → “Visit our website!” 【URLの例】 “Check this link: https://example.com/page” → URLを除去 → “Check this link: ”

HTMLタグの除去(BeautifulSoupを使用)

HTMLの解析にはBeautifulSoupライブラリを使います。 Google Colabでは最初からインストールされています。

# HTMLタグ除去のコード from bs4 import BeautifulSoup # HTML解析ライブラリ html_text = “Check this <b>amazing</b> content!” # BeautifulSoupでHTMLを解析 # ‘html.parser’ はPython標準のHTMLパーサー soup = BeautifulSoup(html_text, ‘html.parser’) # get_text() でタグを除いたテキストだけを取得 text_only = soup.get_text() print(“タグ除去後:”, text_only)
実行結果: タグ除去後: Check this amazing content!

URLの除去(正規表現を使用)

# URL除去のコード import re text = “Visit our site at https://example.com/page for more info” # URLパターンにマッチする正規表現 # http または https で始まり、空白以外の文字が続くもの url_pattern = r’http\S+’ # URLを空文字に置換(=削除) cleaned = re.sub(url_pattern, ”, text) print(“URL除去後:”, cleaned)
実行結果: URL除去後: Visit our site at for more info
💡 正規表現パターンの解説
  • http:「http」という文字列にマッチ
  • \S:空白以外の任意の文字にマッチ
  • +:1回以上の繰り返し
  • \S+:空白以外の文字が1つ以上続くパターン

2-5. 絵文字の除去

📝 絵文字の扱い

SNSのテキストには絵文字が多く含まれます。 感情分析では有用な場合もありますが、通常は削除します。

# 絵文字除去のコード import re text = “Hello! 😊 This is great 🎉 See you 👋” # 絵文字のUnicode範囲を指定した正規表現パターン emoji_pattern = re.compile(“[” u”\U0001F600-\U0001F64F” # 顔の絵文字 u”\U0001F300-\U0001F5FF” # 記号・絵文字 u”\U0001F680-\U0001F6FF” # 乗り物・地図記号 u”\U0001F1E0-\U0001F1FF” # 国旗 “]+”, flags=re.UNICODE) # 絵文字を空文字に置換 cleaned = emoji_pattern.sub(”, text) print(“絵文字除去後:”, cleaned)
実行結果: 絵文字除去後: Hello! This is great See you

2-6. テキストクリーニングの完成コード

これまで学んだクリーニング処理をまとめた関数を作成します。

# テキストクリーニング完成コード import re import string from bs4 import BeautifulSoup def clean_text(text): “””テキストをクリーニングする関数””” # 1. HTMLタグの除去 text = BeautifulSoup(text, ‘html.parser’).get_text() # 2. URLの除去 text = re.sub(r’http\S+’, ”, text) # 3. 絵文字の除去 emoji_pattern = re.compile(“[” u”\U0001F600-\U0001F64F” u”\U0001F300-\U0001F5FF” u”\U0001F680-\U0001F6FF” u”\U0001F1E0-\U0001F1FF” “]+”, flags=re.UNICODE) text = emoji_pattern.sub(”, text) # 4. 小文字化 text = text.lower() # 5. 句読点の除去 text = text.translate(str.maketrans(”, ”, string.punctuation)) # 6. 余分な空白を1つに text = re.sub(r’\s+’, ‘ ‘, text).strip() return text # テスト sample = “Check this <b>AMAZING</b> link: https://test.com 😊!!” result = clean_text(sample) print(“クリーニング前:”, sample) print(“クリーニング後:”, result)
実行結果: クリーニング前: Check this <b>AMAZING</b> link: https://test.com 😊!! クリーニング後: check this amazing link

✂️ 3. トークン化(Tokenization)

トークン化とは、テキストを意味のある単位(トークン)に分割することです。 NLPの最も基本的な処理の1つです。

3-1. トークン化とは何か?

📝 トークン化の定義

テキストを「トークン」と呼ばれる小さな単位に分割する処理です。 トークンは通常、単語や句読点1つ1つを指します。

【トークン化の例】 入力: “I love NLP!” トークン化後: [“I”, “love”, “NLP”, “!”] → 4つのトークンに分割された

3-2. トークン化の3つのレベル

トークン化には、分割する粒度によって3つのレベルがあります。

【レベル1:文トークン化(Sentence Tokenization)】 文章を文に分割 “Hello. How are you?” → [“Hello.”, “How are you?”] 【レベル2:単語トークン化(Word Tokenization)】 文を単語に分割 “I love NLP” → [“I”, “love”, “NLP”] 【レベル3:サブワードトークン化(Subword Tokenization)】 単語をさらに小さい単位に分割 “unhappiness” → [“un”, “happi”, “ness”]

3-3. 文トークン化の実装

📝 文トークン化とは?

長い文章を、個別の文に分割する処理です。 ピリオド、感嘆符、疑問符などで文を区切ります。

NLTKライブラリを使って文トークン化を行います。 Google Colabでは、最初に必要なデータをダウンロードする必要があります。

# 文トークン化のコード import nltk # 必要なデータをダウンロード(初回のみ実行) # ‘punkt’ は文分割に必要なデータ nltk.download(‘punkt’) # サンプルテキスト text = “Hello. How are you? I’m fine! Thanks for asking.” # sent_tokenize() で文に分割 sentences = nltk.sent_tokenize(text) print(“元のテキスト:”) print(text) print(“\n文トークン化後:”) for i, sent in enumerate(sentences): print(f” 文{i+1}: {sent}”)
実行結果: 元のテキスト: Hello. How are you? I’m fine! Thanks for asking. 文トークン化後: 文1: Hello. 文2: How are you? 文3: I’m fine! 文4: Thanks for asking.

3-4. 単語トークン化の実装

📝 単語トークン化とは?

文を単語単位に分割する処理です。 英語の場合、基本的にスペースで区切ります。

NLTKを使った単語トークン化

# 単語トークン化のコード(NLTK) import nltk nltk.download(‘punkt’) # 初回のみ text = “Natural language processing is amazing!” # word_tokenize() で単語に分割 tokens = nltk.word_tokenize(text) print(“元のテキスト:”, text) print(“トークン:”, tokens) print(“トークン数:”, len(tokens))
実行結果: 元のテキスト: Natural language processing is amazing! トークン: [‘Natural’, ‘language’, ‘processing’, ‘is’, ‘amazing’, ‘!’] トークン数: 6
💡 注意点

句読点「!」も1つのトークンとしてカウントされています。 必要に応じて、前処理で句読点を除去しておくと良いでしょう。

spaCyを使った単語トークン化

spaCyはより高度なNLPライブラリで、産業用途に最適化されています。

# 単語トークン化のコード(spaCy) import spacy # 英語モデルをロード # Google Colabでは事前にインストールが必要: # !python -m spacy download en_core_web_sm nlp = spacy.load(‘en_core_web_sm’) text = “Natural language processing is amazing!” # テキストを処理 doc = nlp(text) # 各トークンを取得 tokens = [token.text for token in doc] print(“元のテキスト:”, text) print(“トークン:”, tokens)
実行結果: 元のテキスト: Natural language processing is amazing! トークン: [‘Natural’, ‘language’, ‘processing’, ‘is’, ‘amazing’, ‘!’]

3-5. 英語と日本語のトークン化の違い

⚠️ 日本語は単語の区切りがない

英語はスペースで単語が区切られていますが、 日本語には単語の区切りがありません。

【英語の場合:簡単】 “I love NLP” → スペースで区切るだけ → [“I”, “love”, “NLP”] 【日本語の場合:難しい】 “私はNLPが好きです” → どこで区切る? → “私/は/NLP/が/好き/です” (形態素解析が必要)
📝 日本語のトークン化

日本語のトークン化には「形態素解析」という特殊な処理が必要です。 これについてはSTEP 4で詳しく学びます。

3-6. サブワードトークン化

📝 サブワードトークン化とは?

単語をさらに小さい単位(サブワード)に分割する手法です。 BERTやGPTなどの最新モデルで使われています。

なぜサブワードトークン化が必要か?

【問題:未知語(OOV: Out-Of-Vocabulary)】 訓練データで学習した単語: “play”, “playing”, “played” テストデータに出現: “replaying” ← 訓練データにない! → 単語トークン化だと「未知語」として扱われ、意味を理解できない 【解決:サブワードに分割】 “replaying” → [“re”, “play”, “ing”] → “play” は知っている! → 接頭辞 “re” は「再び」の意味 → 接尾辞 “ing” は進行形 → 「再び再生している」と推測できる!
【サブワードトークン化の例】 ■ “unhappiness”(不幸) 単語トークン化: [“unhappiness”] サブワード化: [“un”, “happi”, “ness”] (否定 + 幸せ + 名詞化) ■ “unbelievable”(信じられない) 単語トークン化: [“unbelievable”] サブワード化: [“un”, “believ”, “able”] (否定 + 信じる + 可能)
✅ 主なサブワードトークン化手法
  • BPE(Byte Pair Encoding):GPTシリーズで使用
  • WordPiece:BERTで使用
  • SentencePiece:言語に依存しない手法、多言語モデルで使用

これらの詳細はTransformerを学ぶ際に解説します。

🚫 4. ストップワードの除去

4-1. ストップワードとは?

📝 ストップワードの定義

ストップワード(Stop Words)とは、 出現頻度は高いが、意味的には重要でない単語のことです。

【英語のストップワード例】 冠詞: a, an, the be動詞: is, are, was, were, be, been 前置詞: in, on, at, to, for, of, with 接続詞: and, or, but 代名詞: I, you, he, she, it, they, we 【日本語のストップワード例】 助詞: は、が、を、に、で、の、と、も、や 助動詞: です、ます、た、だ 接続詞: そして、また、しかし

4-2. なぜストップワードを除去するのか?

【例文】 “This is a great introduction to NLP” 【ストップワードを含む場合】 トークン: [“this”, “is”, “a”, “great”, “introduction”, “to”, “nlp”] → 7単語すべてを処理する必要がある 【ストップワード除去後】 トークン: [“great”, “introduction”, “nlp”] → 重要な3単語だけを処理すれば良い メリット: ・処理する単語数が減る → 計算が速くなる ・ノイズが減る → モデルの精度が上がることがある

4-3. NLTKでストップワード除去

NLTKには、多くの言語のストップワードリストが用意されています。

# ストップワード除去のコード import nltk from nltk.corpus import stopwords from nltk.tokenize import word_tokenize # 必要なデータをダウンロード nltk.download(‘punkt’) nltk.download(‘stopwords’) # 英語のストップワードリストを取得 stop_words = set(stopwords.words(‘english’)) # ストップワードの一部を表示 print(“ストップワードの例(最初の20個):”) print(list(stop_words)[:20])
実行結果: ストップワードの例(最初の20個): [‘herself’, ‘between’, “wasn’t”, ‘all’, ‘during’, ‘into’, ‘same’, ‘whom’, ‘after’, ‘do’, “hadn’t”, ‘under’, ‘or’, ‘theirs’, ‘were’, ‘being’, ‘down’, ‘couldn’, ‘out’, ‘further’]

ストップワードを除去する

# ストップワード除去の実装 text = “This is a great introduction to natural language processing” # 1. トークン化(小文字に変換) tokens = word_tokenize(text.lower()) print(“トークン化後:”, tokens) # 2. ストップワード除去 # リスト内包表記で、ストップワードに含まれない単語だけを残す filtered_tokens = [word for word in tokens if word not in stop_words] print(“除去後:”, filtered_tokens)
実行結果: トークン化後: [‘this’, ‘is’, ‘a’, ‘great’, ‘introduction’, ‘to’, ‘natural’, ‘language’, ‘processing’] 除去後: [‘great’, ‘introduction’, ‘natural’, ‘language’, ‘processing’]
💡 コードの解説

[word for word in tokens if word not in stop_words]

これは「リスト内包表記」と呼ばれるPythonの書き方です:

  • for word in tokens:tokensリストの各要素をwordとして取り出す
  • if word not in stop_words:wordがストップワードでなければ
  • 最初の word:条件を満たすwordを新しいリストに追加

4-4. ストップワード除去の注意点

⚠️ ストップワード除去のデメリット
  • 文脈が失われる:“not good” から “not” を除去すると意味が逆になる
  • 固有表現が壊れる:“The Who”(バンド名)から “The” を除去すると意味不明
【問題例】 元の文: “This movie is not good” 意味: この映画は良くない(否定) ストップワード除去後: [“movie”, “good”] 意味: 映画、良い(肯定に見える!) → “not” を除去したことで、意味が逆転してしまった!
💡 ストップワード除去を使うべき場面

除去する場合:

  • 従来の機械学習(Bag of Words、TF-IDF)を使う場合
  • 文書の類似度計算
  • キーワード抽出

除去しない場合:

  • 深層学習モデル(BERT、GPT)を使う場合
  • 感情分析(”not” が重要)
  • 質問応答(文脈が重要)

🌿 5. ステミングとレマ化

ステミングレマ化は、 単語を基本形に変換する技術です。 異なるアプローチですが、目的は同じです。

5-1. なぜ基本形に変換するのか?

【問題】活用形が異なると別の単語として扱われる “run” → 単語ID: 1 “running” → 単語ID: 2 “ran” → 単語ID: 3 “runs” → 単語ID: 4 → 同じ「走る」という意味なのに、4つの異なる単語に! → 語彙数が増えすぎる 【解決】基本形に変換 “run” → “run” → 単語ID: 1 “running” → “run” → 単語ID: 1 “ran” → “run” → 単語ID: 1 “runs” → “run” → 単語ID: 1 → すべて同じ単語として扱える!

5-2. ステミング(Stemming)とは?

📝 ステミングの定義

ルールベースで単語の語尾を機械的に削除し、語幹を取り出す手法です。 辞書を使わないため、高速に処理できます。

【ステミングのルール例】 ルール1: -ing を削除 → “running” → “runn” → “run” ルール2: -ed を削除 → “played” → “play” ルール3: -s を削除 → “cats” → “cat” ルール4: -ly を削除 → “easily” → “easi” ※ 単純なルールなので、正しくない結果になることもある

Pythonでステミングを実装

# ステミングのコード from nltk.stem import PorterStemmer # Porter Stemmerを作成 # Porter Stemmerは最も広く使われているステミングアルゴリズム stemmer = PorterStemmer() # テストする単語 words = [“running”, “runs”, “ran”, “runner”, “easily”, “fairly”, “studies”] # 各単語をステミング print(“【ステミング結果】”) for word in words: stemmed = stemmer.stem(word) print(f” {word:12} → {stemmed}”)
実行結果: 【ステミング結果】 running → run runs → run ran → ran runner → runner easily → easili fairly → fairli studies → studi
⚠️ ステミングの問題点
  • “ran” が “run” にならない:不規則変化に対応できない
  • “easily” が “easili” になる:意味不明な語幹が生成される
  • “studies” が “studi” になる:正しい語幹ではない

5-3. レマ化(Lemmatization)とは?

📝 レマ化の定義

辞書を使って、単語を正しい基本形(見出し語)に変換する手法です。 ステミングより精度が高いですが、処理は遅くなります。

【レマ化の例】 “running” → “run” (辞書で正しく変換) “ran” → “run” (不規則変化も対応!) “better” → “good” (比較級から原級へ) “geese” → “goose” (不規則な複数形も対応) “is” → “be” (be動詞の活用も対応)

Pythonでレマ化を実装

# レマ化のコード import nltk from nltk.stem import WordNetLemmatizer # 必要なデータをダウンロード nltk.download(‘wordnet’) nltk.download(‘omw-1.4′) # レマタイザーを作成 lemmatizer = WordNetLemmatizer() # テストする単語と品詞 # pos=’v’ は動詞、pos=’n’ は名詞、pos=’a’ は形容詞 test_cases = [ (“running”, “v”), # 動詞として処理 (“ran”, “v”), # 動詞として処理 (“better”, “a”), # 形容詞として処理 (“geese”, “n”), # 名詞として処理 (“studies”, “v”), # 動詞として処理 ] print(“【レマ化結果】”) for word, pos in test_cases: lemma = lemmatizer.lemmatize(word, pos=pos) print(f” {word:12} ({pos}) → {lemma}”)
実行結果: 【レマ化結果】 running (v) → run ran (v) → run better (a) → good geese (n) → goose studies (v) → study
💡 品詞(pos)の指定が重要

レマ化では品詞を指定すると精度が上がります:

  • pos='v':動詞(verb)
  • pos='n':名詞(noun)
  • pos='a':形容詞(adjective)
  • pos='r':副詞(adverb)

5-4. ステミング vs レマ化の比較

項目 ステミング レマ化
手法 ルールベース(語尾削除) 辞書ベース(正しい変換)
速度 高速 やや遅い
精度 低い(不正確な場合あり) 高い(正しい基本形)
出力 語幹(意味不明な場合あり) 正しい単語
“easily”の結果 “easili” ✗ “easily” or “easy” ✓
“ran”の結果 “ran” ✗ “run” ✓
💡 どちらを使うべき?

ステミングを選ぶ場合:

  • 処理速度を重視する
  • 大量のデータを処理する
  • 単純な検索システムを作る

レマ化を選ぶ場合:

  • 精度を重視する
  • 意味解析が重要
  • 感情分析や質問応答を行う

🛠️ 6. 実装:前処理パイプラインの完成

これまで学んだ前処理を組み合わせて、完全なパイプラインを作成します。

6-1. NLTK vs spaCyの比較

項目 NLTK spaCy
対象 教育・研究向け 実務・プロダクション向け
速度 やや遅い 非常に高速
学習コスト 初心者に優しい やや高い
機能 アルゴリズム多数 深層学習ベース
推奨用途 学習、実験 本番システム

6-2. NLTKで前処理パイプラインを作成

NLTKを使った完全な前処理関数を作成します。 コードを段階的に解説します。

ステップ1:必要なライブラリのインポートとダウンロード

# NLTKの前処理パイプライン – Part 1 import nltk from nltk.corpus import stopwords from nltk.stem import WordNetLemmatizer from nltk.tokenize import word_tokenize import string # 必要なデータをダウンロード(初回のみ) nltk.download(‘punkt’) nltk.download(‘stopwords’) nltk.download(‘wordnet’) nltk.download(‘omw-1.4’)

ステップ2:前処理関数の定義

# NLTKの前処理パイプライン – Part 2 def preprocess_text_nltk(text): “”” NLTKを使ったテキスト前処理関数 処理内容: 1. 小文字化 2. トークン化 3. 句読点の除去 4. ストップワードの除去 5. レマ化 “”” # 1. 小文字化 # すべての文字を小文字に変換して統一 text = text.lower() # 2. トークン化 # 文を単語のリストに分割 tokens = word_tokenize(text) # 3. 句読点とストップワードの除去 # string.punctuation: すべての句読点 # stopwords.words(‘english’): 英語のストップワード stop_words = set(stopwords.words(‘english’)) tokens = [token for token in tokens if token not in string.punctuation and token not in stop_words] # 4. レマ化 # 各単語を基本形に変換 lemmatizer = WordNetLemmatizer() tokens = [lemmatizer.lemmatize(token, pos=’v’) for token in tokens] return tokens

ステップ3:動作テスト

# NLTKの前処理パイプライン – Part 3(テスト) # テスト用のテキスト sample_text = “Running through the beautiful woods, I saw many amazing trees!” # 前処理を実行 result = preprocess_text_nltk(sample_text) print(“【入力テキスト】”) print(sample_text) print(“\n【前処理後】”) print(result)
実行結果: 【入力テキスト】 Running through the beautiful woods, I saw many amazing trees! 【前処理後】 [‘run’, ‘beautiful’, ‘wood’, ‘see’, ‘many’, ‘amaze’, ‘tree’]

6-3. spaCyで前処理パイプラインを作成

spaCyを使うと、より簡潔に前処理を記述できます。

# spaCyの前処理パイプライン import spacy # 英語モデルをロード # 初回は以下のコマンドでダウンロードが必要: # !python -m spacy download en_core_web_sm nlp = spacy.load(‘en_core_web_sm’) def preprocess_text_spacy(text): “”” spaCyを使ったテキスト前処理関数 spaCyは1回の処理で以下を同時に行う: – トークン化 – 品詞タグ付け – レマ化 – ストップワード判定 “”” # テキストを処理(全ての解析が自動的に行われる) doc = nlp(text) # 各トークンについて: # – token.lemma_: レマ化された形 # – token.is_stop: ストップワードかどうか # – token.is_punct: 句読点かどうか # – token.is_space: 空白かどうか tokens = [token.lemma_.lower() for token in doc if not token.is_stop and not token.is_punct and not token.is_space] return tokens # テスト sample_text = “Running through the beautiful woods, I saw many amazing trees!” result = preprocess_text_spacy(sample_text) print(“【入力テキスト】”) print(sample_text) print(“\n【前処理後(spaCy)】”) print(result)
実行結果: 【入力テキスト】 Running through the beautiful woods, I saw many amazing trees! 【前処理後(spaCy)】 [‘run’, ‘beautiful’, ‘wood’, ‘see’, ‘amazing’, ‘tree’]
💡 spaCyの便利な点

spaCyは nlp(text) を呼ぶだけで、 トークン化・品詞タグ付け・レマ化などが全て自動で行われます。 各トークンの属性(is_stopis_punct など)で 簡単にフィルタリングできます。

📝 練習問題

このステップで学んだ内容を確認しましょう。

問題1:テキストクリーニング

次のテキストに対して、小文字化と句読点除去を行った結果はどれですか?

入力: “Hello, World! Welcome to NLP.”
  1. “Hello World Welcome to NLP”
  2. “hello world welcome to nlp”
  3. “Hello world Welcome to NLP”
  4. “hello, world! welcome to nlp.”
正解:b

処理の手順:

  1. 小文字化:“Hello, World! Welcome to NLP.” → “hello, world! welcome to nlp.”
  2. 句読点除去:“hello, world! welcome to nlp.” → “hello world welcome to nlp”

各選択肢の解説:

  • a. 大文字が残っているので不正解
  • b. 正解(小文字化 + 句読点除去の両方が適用)
  • c. 大文字が一部残っているので不正解
  • d. 句読点が残っているので不正解

問題2:トークン化

次のうち、単語トークン化の説明として正しいものはどれですか?

  1. 文章を文に分割すること
  2. 文を単語に分割すること
  3. 単語をさらに小さい単位に分割すること
  4. 文章から重要な単語だけを抽出すること
正解:b

トークン化の3つのレベル:

  • 文トークン化(a):文章を文に分割
    例:”Hello. How are you?” → [“Hello.”, “How are you?”]
  • 単語トークン化(b):文を単語に分割
    例:”I love NLP” → [“I”, “love”, “NLP”]
  • サブワードトークン化(c):単語をさらに小さい単位に分割
    例:”unhappiness” → [“un”, “happi”, “ness”]

d.は「キーワード抽出」や「ストップワード除去」に近い説明であり、トークン化ではありません。

問題3:ストップワード

次の単語のうち、英語のストップワードとして扱われる可能性が最も低いものはどれですか?

  1. “the”
  2. “is”
  3. “machine”
  4. “and”
正解:c

ストップワードは、出現頻度は高いが意味的には重要でない単語です。

各選択肢の解説:

  • a. “the”(冠詞):典型的なストップワード
  • b. “is”(be動詞):典型的なストップワード
  • c. “machine”(名詞):具体的な意味を持つ単語なので、ストップワードではない
  • d. “and”(接続詞):典型的なストップワード

“machine”(機械)は具体的な意味を持つ名詞なので、 文の意味を理解する上で重要な単語です。

問題4:ステミング vs レマ化

次の説明のうち、レマ化(Lemmatization)の特徴として正しいものはどれですか?

  1. ルールベースで語尾を機械的に削除する
  2. 辞書を使って正しい基本形に変換する
  3. ステミングよりも高速に処理できる
  4. 意味不明な語幹が生成されることがある
正解:b

ステミングとレマ化の違い:

  • ステミング:ルールベースで語尾を機械的に削除(a, d の特徴)
  • レマ化:辞書を使って正しい基本形に変換(b)

各選択肢の解説:

  • a. ステミングの特徴
  • b. レマ化の特徴(正解)
  • c. 誤り(レマ化は辞書参照があるため、ステミングより遅い)
  • d. ステミングの特徴(”easily”→”easili”など)

問題5:前処理パイプライン

次のテキスト前処理の手順を、一般的な順序に並び替えてください。

  1. レマ化
  2. 小文字化
  3. ストップワード除去
  4. トークン化
正解:B → D → C → A

一般的な前処理パイプラインの順序:

  1. 小文字化(B):まず文字を統一(文字列全体に対して処理)
  2. トークン化(D):文字列を単語のリストに分割
  3. ストップワード除去(C):不要な単語を削除
  4. レマ化(A):残った単語を基本形に変換

理由:
小文字化は文字列に対する処理なので最初に行います。 トークン化で単語に分割した後、不要な単語(ストップワード)を除去し、 最後に残った単語をレマ化します。

📝 STEP 2 のまとめ

✅ このステップで学んだこと
  • テキスト前処理の目的:ノイズ除去、正規化、標準化、次元削減
  • テキストクリーニング:小文字化、句読点除去、HTML/URL除去、絵文字除去
  • トークン化:文→単語→サブワード の3レベル
  • ストップワード除去:頻出だが意味の薄い単語を削除
  • ステミング:語尾を機械的に削除(高速だが精度低)
  • レマ化:辞書で正しい基本形に変換(高精度だが遅い)
  • NLTK vs spaCy:学習・研究用 vs 実務・本番用
💡 重要ポイント

テキスト前処理はNLPの基礎中の基礎です。 前処理の品質が、最終的なモデルの性能を大きく左右します。

ただし、深層学習時代では前処理の役割が変化しています:

  • BERTやGPTは生のテキストを直接処理できる
  • ストップワード除去やレマ化は不要な場合が多い
  • サブワードトークン化が主流に

このコースでは、伝統的手法と最新手法の両方を学んでいきます。

🎯 次のステップの準備

次のSTEP 3では、テキストのベクトル化を学びます。

Bag of Words、TF-IDF、N-gramなど、 テキストを数値(ベクトル)に変換する伝統的な手法を習得していきましょう!

📝

学習メモ

自然言語処理(NLP) - Step 2

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE