第 12 章 ソースコード一覧¶
書籍第 12 章「自然言語処理の基礎」に掲載しているソースコードの一覧です。番号は書籍の「入力」番号と対応しています。上のバッジから、この章のコードをまとめた Google Colab ノートブックを開けます。
入力 12.1: join・split・replaceによる文字列操作¶
words = ["自然", "言語", "処理"]
print(" ".join(words)) # 自然 言語 処理
text = "Python は 自然言語処理 に 便利 です"
print(text.split(" ")) # ["Python", "は", "自然言語処理", ...]
s = "今日は天気が良いです。明日も天気が良いでしょう。"
print(s.replace("天気が良い", "晴れ")) # 今日は晴れです。明日も晴れでしょう。
入力 12.2: テキストファイルの作成¶
# サンプルファイルの作成
text = "自然言語処理は人工知能の一分野です。\nテキストデータを分析する技術です。\n"
with open("sample.txt", "w", encoding="utf-8") as f:
f.write(text)
入力 12.3: テキストファイルの読み込み¶
入力 12.4: readlinesによる行ごとの読み込み¶
入力 12.5: 英語と日本語の単語分割の違い¶
# 英語: スペースで単語に分割できる
english = "Natural language processing is important"
print(english.split(" "))
# 日本語: スペースがないため単純に分割できない
japanese = "自然言語処理は重要です"
print(japanese.split(" "))
入力 12.6: MeCabのインストール¶
入力 12.7: parseによる形態素解析¶
入力 12.8: -Owakatiオプションによる分かち書き¶
import MeCab
tagger = MeCab.Tagger("-Owakati")
text = "自然言語処理を学びます"
result = tagger.parse(text)
print(result)
入力 12.9: parseToNodeによる品詞情報の取得¶
import MeCab
tagger = MeCab.Tagger()
text = "自然言語処理を学びます"
node = tagger.parseToNode(text)
while node:
# 表層形(surface)と品詞などの情報(feature)
if node.surface != "":
word = node.surface
pos = node.feature.split(",")[0] # 品詞の取得
print(f"{word}\t{pos}")
node = node.next
入力 12.10: replaceによるテキストクリーニング¶
text = "今日の\t天気は<b>晴れ</b>です。\n"
# タブ文字の除去
text = text.replace("\t", "")
# 改行文字の除去
text = text.replace("\n", "")
# HTMLタグの除去
text = text.replace("<b>", "")
text = text.replace("</b>", "")
print(text)
入力 12.11: 正規表現によるテキストクリーニング¶
import re
text = "今日の\t天気は<b>晴れ</b>です。\n"
# タブと改行を除去
text = re.sub(r"[\t\n]", "", text)
# HTMLタグを除去
text = re.sub(r"<.*?>", "", text)
print(text)
入力 12.12: URL・メールアドレス・電話番号の除去¶
import re
text = """
お問い合わせは https://example.com まで。
メール: info@example.com
電話: 03-1234-5678 または 090-1234-5678
"""
# URLの除去
text = re.sub(r"https?://[\w/:%#\$&\?\(\)~\.=\+\-]+", "", text)
# メールアドレスの除去
text = re.sub(r"[\w\.-]+@[\w\.-]+\.\w+", "", text)
# 電話番号の除去(ハイフン区切り)
text = re.sub(r"\d{2,4}-\d{2,4}-\d{4}", "", text)
print(text)
入力 12.13: 余分な空白の整理¶
import re
text = " これは テスト です "
# 連続する空白を1つに置換
text = re.sub(r"\s+", " ", text)
# 前後の空白を除去
text = text.strip()
print(text)
入力 12.14: ストップワードの除去¶
import MeCab
# ストップワードの定義
stop_words = ["は", "の", "が", "を", "に", "へ", "と", "で", "た",
"です", "ます", "する", "いる", "ある", "こと", "もの",
"それ", "これ", "ない", "なる", "れる", "られる"]
tagger = MeCab.Tagger("-Owakati")
text = "自然言語処理は人工知能の重要な分野です"
words = tagger.parse(text).strip().split(" ")
print("除去前:", words)
# ストップワードの除去
filtered = [w for w in words if w not in stop_words]
print("除去後:", filtered)
入力 12.15: 品詞によるフィルタリング¶
import MeCab
tagger = MeCab.Tagger()
text = "機械学習の技術は急速に進歩している"
# 名詞、動詞、形容詞のみを抽出
target_pos = ["名詞", "動詞", "形容詞"]
words = []
node = tagger.parseToNode(text)
while node:
if node.surface != "":
pos = node.feature.split(",")[0]
if pos in target_pos:
words.append(node.surface)
node = node.next
print(words)
入力 12.16: 前処理パイプラインの関数化¶
import re
import MeCab
# テキストの前処理パイプライン
def preprocess(text):
# 1. テキストクリーニング
text = re.sub(r"https?://[\w/:%#\$&\?\(\)~\.=\+\-]+", "", text) # URL除去
text = re.sub(r"[\w\.-]+@[\w\.-]+\.\w+", "", text) # メールアドレス除去
text = re.sub(r"\d{2,4}-\d{2,4}-\d{4}", "", text) # 電話番号除去
text = re.sub(r"[!-/:-@\[-`{-~]", "", text) # 半角記号除去
text = re.sub(r"[!-/:-@[-`{-~、。・「」『』【】]", "", text) # 全角記号除去
text = re.sub(r"\s+", " ", text).strip() # 空白の正規化
# 2. 形態素解析と品詞フィルタリング
tagger = MeCab.Tagger()
target_pos = ["名詞", "動詞", "形容詞"]
words = []
node = tagger.parseToNode(text)
while node:
if node.surface != "":
pos = node.feature.split(",")[0]
if pos in target_pos:
words.append(node.surface)
node = node.next
return words
入力 12.17: 前処理パイプラインの実行¶
text = "詳細は https://example.com をご覧ください!お問い合わせ: info@test.com"
result = preprocess(text)
print(result)
入力 12.18: 複数文書への前処理の適用¶
documents = [
"自然言語処理は人工知能の一分野です。",
"機械学習を使ってテキストを分析します。",
"深層学習の発展により精度が向上しました。",
]
processed_docs = []
for doc in documents:
words = preprocess(doc)
processed_docs.append(" ".join(words))
for i, doc in enumerate(processed_docs):
print(f"文書{i+1}: {doc}")
入力 12.19: CountVectorizerによるBoWベクトル化¶
import MeCab
from sklearn.feature_extraction.text import CountVectorizer
# サンプル文書
documents = [
"自然言語処理は人工知能の一分野です",
"機械学習で自然言語を処理します",
"深層学習は機械学習の一手法です",
]
# MeCabで分かち書き
tagger = MeCab.Tagger("-Owakati")
wakati_docs = [tagger.parse(doc).strip() for doc in documents]
print("分かち書き結果:")
for i, doc in enumerate(wakati_docs):
print(f" 文書{i+1}: {doc}")
# CountVectorizerでBoWベクトルを生成
vectorizer = CountVectorizer()
bow_matrix = vectorizer.fit_transform(wakati_docs)
# 語彙の確認
print("\n語彙:", vectorizer.get_feature_names_out())
# BoW行列の表示
print("\nBoW行列:")
print(bow_matrix.toarray())
入力 12.20: fit_transformとtransformの使い分け¶
from sklearn.feature_extraction.text import CountVectorizer
# 訓練データ
train_docs = ["猫 は かわいい", "犬 も かわいい"]
# テストデータ
test_docs = ["猫 と 犬 は 友達"]
# 訓練データで学習+変換(fit_transform)
# token_pattern で1文字の単語も語彙に含める
vectorizer = CountVectorizer(token_pattern=r"(?u)\b\w+\b")
train_matrix = vectorizer.fit_transform(train_docs)
print("学習した語彙:", vectorizer.get_feature_names_out())
print("訓練データのベクトル:")
print(train_matrix.toarray())
# テストデータには transform のみ適用
test_matrix = vectorizer.transform(test_docs)
print("\nテストデータのベクトル:")
print(test_matrix.toarray())
入力 12.21: CountVectorizerの主なパラメータ¶
from sklearn.feature_extraction.text import CountVectorizer
docs = ["猫 は かわいい 動物", "犬 も かわいい 動物", "猫 も 犬 も かわいい"]
tp = r"(?u)\b\w+\b" # 1文字の単語も語彙に含める設定
# max_df: 出現頻度が高すぎる単語を除外(全文書の80%より多くに出現する単語を除外)
vec1 = CountVectorizer(max_df=0.8, token_pattern=tp)
result1 = vec1.fit_transform(docs)
print("max_df=0.8 の語彙:", vec1.get_feature_names_out())
# min_df: 出現頻度が低すぎる単語を除外(2文書未満にしか出現しない単語を除外)
vec2 = CountVectorizer(min_df=2, token_pattern=tp)
result2 = vec2.fit_transform(docs)
print("min_df=2 の語彙:", vec2.get_feature_names_out())
# max_features: 語彙の最大数を指定(上位3語のみ)
vec3 = CountVectorizer(max_features=3, token_pattern=tp)
result3 = vec3.fit_transform(docs)
print("max_features=3 の語彙:", vec3.get_feature_names_out())
入力 12.22: ngram_rangeによるN-gramの生成¶
from sklearn.feature_extraction.text import CountVectorizer
docs = ["自然 言語 処理 を 学ぶ"]
tp = r"(?u)\b\w+\b" # 1文字の単語も語彙に含める設定
# ユニグラムのみ(デフォルト)
vec_uni = CountVectorizer(token_pattern=tp, ngram_range=(1, 1))
vec_uni.fit(docs)
print("ユニグラム:", vec_uni.get_feature_names_out())
# バイグラムのみ
vec_bi = CountVectorizer(token_pattern=tp, ngram_range=(2, 2))
vec_bi.fit(docs)
print("バイグラム:", vec_bi.get_feature_names_out())
# ユニグラム + バイグラム
vec_both = CountVectorizer(token_pattern=tp, ngram_range=(1, 2))
vec_both.fit(docs)
print("ユニグラム+バイグラム:", vec_both.get_feature_names_out())
入力 12.23: TfidfVectorizerによるTF-IDFベクトル化¶
import MeCab
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
# サンプル文書
documents = [
"自然言語処理は人工知能の一分野です",
"機械学習で自然言語を処理します",
"深層学習も自然言語を処理します",
]
# MeCabで分かち書き
tagger = MeCab.Tagger("-Owakati")
wakati_docs = [tagger.parse(doc).strip() for doc in documents]
# TfidfVectorizerでTF-IDFベクトルを生成
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(wakati_docs)
# 結果をDataFrameで見やすく表示
feature_names = tfidf_vectorizer.get_feature_names_out()
df = pd.DataFrame(
tfidf_matrix.toarray(),
columns=feature_names,
index=["文書1", "文書2", "文書3"]
)
print(df.round(2))
入力 12.24: BoWとTF-IDFの比較¶
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
documents = [
"猫 は かわいい 動物",
"犬 も かわいい 動物",
"猫 は 自由 な 動物",
]
tp = r"(?u)\b\w+\b" # 1文字の単語も語彙に含める設定
# Bag-of-Words
count_vec = CountVectorizer(token_pattern=tp)
bow = count_vec.fit_transform(documents)
print("【Bag-of-Words】")
df_bow = pd.DataFrame(bow.toarray(), columns=count_vec.get_feature_names_out(),
index=["文書1", "文書2", "文書3"])
print(df_bow)
# TF-IDF
tfidf_vec = TfidfVectorizer(token_pattern=tp)
tfidf = tfidf_vec.fit_transform(documents)
print("\n【TF-IDF】")
df_tfidf = pd.DataFrame(tfidf.toarray(), columns=tfidf_vec.get_feature_names_out(),
index=["文書1", "文書2", "文書3"])
print(df_tfidf.round(2))
入力 12.25: 文書間のコサイン類似度の計算¶
import MeCab
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# サンプル文書コーパス
documents = [
"機械学習はデータからパターンを学習する技術です",
"深層学習はニューラルネットワークを用いた機械学習の手法です",
"自然言語処理はテキストデータを分析する技術です",
"画像認識は写真や動画から物体を検出する技術です",
"機械学習を使ってテキストを分類することができます",
]
# MeCabで分かち書き
tagger = MeCab.Tagger("-Owakati")
wakati_docs = [tagger.parse(doc).strip() for doc in documents]
# TF-IDFベクトルの生成
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(wakati_docs)
# 全文書間のコサイン類似度を計算
cos_sim = cosine_similarity(tfidf_matrix)
# 結果の表示
labels = [f"文書{i+1}" for i in range(len(documents))]
df_sim = pd.DataFrame(cos_sim, index=labels, columns=labels)
print(df_sim.round(2))
入力 12.26: 類似文書の検索と順位付け¶
import MeCab
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
# クエリに類似した文書を検索して順位付けする
def search_similar(query, documents, vectorizer, tfidf_matrix, top_n=3):
# クエリをMeCabで分かち書き
tagger = MeCab.Tagger("-Owakati")
query_wakati = tagger.parse(query).strip()
# クエリをTF-IDFベクトルに変換(学習済みのvectorizerを使用)
query_vec = vectorizer.transform([query_wakati])
# クエリとコーパス内の各文書とのコサイン類似度を計算
similarities = cosine_similarity(query_vec, tfidf_matrix)[0]
# 類似度の高い順にソート
ranking = np.argsort(similarities)[::-1]
print(f"クエリ: 「{query}」\n")
print("類似文書ランキング:")
for rank, idx in enumerate(ranking[:top_n], 1):
print(f" {rank}位 (類似度: {similarities[idx]:.4f}): {documents[idx]}")
# 検索の実行
query = "テキストデータの分析と分類の方法"
search_similar(query, documents, vectorizer, tfidf_matrix)