論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
自然言語処理(NLP)
Natural Language Processing
テキストを計算機で扱う — 単語の表現から大規模言語モデルまで
NLPテキストTransformerLLM

📍 あなたが今見ているもの

本ページでは、 自然言語処理 (NLP) を統合的に解説します。 トークン化形態素解析BoW/TF-IDFWord2VecBERT埋め込み主要 NLP タスクを一気通貫で扱います。

日本語は分かち書きが必要・敬語や文脈依存が強い・複雑なエンコーディング等、 英語にはない難しさがあります。 本ページは日本語固有の課題も扱います。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

NLPとは トークン化 形態素解析 サブワード ストップワード BoW TF-IDF n-gram Word2Vec GloVe 文脈付き埋め込み BERT 主要タスク 感情分析 固有表現抽出 トピックモデル 機械翻訳 質問応答

💡 30秒で分かる結論

🤔 1. NLP とは・なぜ難しい

人間の言語をコンピュータで処理する分野。 困難要因:

🪓 2. トークン化

テキストを処理単位(トークン)に分割。 多くの NLP の最初のステップ。

2.1 形態素解析(日本語)

英語は空白で分かち書き → 日本語は文字列。 形態素解析器で分割:

1
2
3
4
import fugashi
tagger = fugashi.Tagger()
for word in tagger("日本の首都は東京都です。"):
    print(word.surface, word.feature.pos1, word.feature.lemma)

2.2 サブワード分割

Transformer 系は語彙の固定化のためサブワード(語の一部)に分割:

1
2
3
4
from transformers import AutoTokenizer
tok = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v3')
ids = tok.encode('東京は日本の首都です')
print(tok.convert_ids_to_tokens(ids))

2.3 ストップワード除去

「は」「が」「の」など、 内容語でない単語を除く。 古典的 NLP の前処理。 BERT 系では通常不要。

📊 3. Bag-of-Words(BoW)と TF-IDF

古典的だが今も強力なベースライン特徴化手法。

3.1 BoW

文書 = 単語の出現数ベクトル。 順序情報は捨てる。

3.2 TF-IDF

$$\mathrm{TF}\text{-}\mathrm{IDF}(t, d) = \mathrm{TF}(t, d) \cdot \log\frac{N}{\mathrm{DF}(t)}$$

1
2
3
4
5
6
7
from sklearn.feature_extraction.text import TfidfVectorizer
import fugashi
tagger = fugashi.Tagger()
def tokenize_ja(text):
    return [w.surface for w in tagger(text)]
vec = TfidfVectorizer(tokenizer=tokenize_ja, token_pattern=None, max_features=5000)
X = vec.fit_transform(documents)

3.3 n-gram

連続 n 単語を 1 特徴に。 文脈の一部を表現。 n=1(unigram)、 n=2(bigram)、 n=3(trigram)が標準。

🔤 4. 単語埋め込み

4.1 Word2Vec(Mikolov 2013)

「単語の意味は周囲に現れる単語で決まる」(分布仮説)に基づき、 文脈ウィンドウから単語を予測(Skip-gram)または逆(CBOW)。

1
2
3
4
5
from gensim.models import Word2Vec
sentences = [['東京', 'は', '日本', 'の', '首都'], ['大阪', 'は', '関西', 'の', '中心']]
model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, workers=4)
print(model.wv['東京'])
print(model.wv.most_similar('東京'))

4.2 GloVe

Stanford 2014。 単語共起行列の対数を直接フィット。 Word2Vec と同等の性能。

4.3 FastText

Facebook 2016。 サブワード単位の埋め込み。 未知語にも対応。

🌊 5. 文脈付き埋め込み

同じ単語でも文脈で異なるベクトル:「銀行に預金」と「川の銀行」の「銀行」は別ベクトル。

5.1 BERT(2018)

双方向 Transformer Encoder。 大規模コーパスで Masked LM 事前学習。 分類・抽出系タスクで圧倒的精度。

1
2
3
4
5
6
7
8
9
from transformers import AutoTokenizer, AutoModel
import torch
tok = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v3')
model = AutoModel.from_pretrained('cl-tohoku/bert-base-japanese-v3')
ids = tok('東京は日本の首都です', return_tensors='pt')
with torch.no_grad():
    out = model(**ids)
embedding = out.last_hidden_state.mean(dim=1)  # 文ベクトル
print(embedding.shape)

5.2 SBERT / E5(文埋め込み専用)

文単位の意味類似度を測れるよう、 contrastive learning でファインチューン。 検索・クラスタリングに使う。

5.3 多言語埋め込み

📋 6. 主要 NLP タスク

6.1 文書分類・感情分析

感情極性(positive/negative)、 カテゴリ、 トピック等。

1
2
3
from transformers import pipeline
clf = pipeline('sentiment-analysis', model='koheiduck/bert-japanese-finetuned-sentiment')
print(clf('このサービスはとても便利です'))

6.2 固有表現抽出 (NER)

テキストから人名・地名・組織名等を抽出。 BIO タグ付け。

1
2
3
from transformers import pipeline
ner = pipeline('ner', model='Davlan/bert-base-multilingual-cased-ner-hrl')
print(ner('オバマは2009年にアメリカ大統領になった'))

6.3 文書類似度・検索

文ベクトル間のコサイン類似度。 RAG・FAQ 検索の基盤。

6.4 トピックモデル

6.5 機械翻訳

Encoder-Decoder Transformer が標準。 NMT (Neural MT)。

1
2
trans = pipeline('translation', model='Helsinki-NLP/opus-mt-ja-en')
print(trans('東京は美しい都市です'))

6.6 質問応答 (QA)

6.7 要約

6.8 対話システム

タスク指向 / オープンドメイン。 現代は ChatGPT 系 LLM が主流。

💬 7. LLM とプロンプトエンジニアリング

7.1 主要 LLM

7.2 プロンプト技法

7.3 RAG(検索拡張生成)

  1. クエリを埋め込みベクトル化
  2. ベクトル DB(FAISS・Chroma・Pinecone)で類似文書検索
  3. 取得した文書を LLM のプロンプトに注入
  4. 根拠付き回答を生成

📊 8. NLP の評価指標

⚠️ 9. NLP の落とし穴

落とし穴 対処
日本語に英語向けトークナイザ日本語事前学習モデルとセットで使う。 fugashi/sudachi を活用。
前処理を過剰にBERT 系は素のテキストで OK。 古典手法のときだけ前処理。
小データで巨大 LLM fine-tuneLoRA・プロンプト・Few-shot で対応。
クラス不均衡Macro-F1 で評価、 weighted loss、 リサンプリング。
時系列リーク時系列分割。 訓練に未来データを混ぜない。
BLEU だけで翻訳評価最新は COMET・BERTScore。 人手評価も併用。
LLM 出力をそのまま信用ハルシネーション対策に RAG・根拠検証。

🏋️ 10. 練習問題

SSDSE-B はテキストデータではないため、 wikipedia 日本語コーパス・口コミデータ・ニュース等を併用してください。

Q1. 日本語テキスト 100 件を fugashi で分かち書きし、 TF-IDF + ロジスティック回帰で分類しなさい。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
import fugashi
tagger = fugashi.Tagger()
def tok(text):
    return [w.surface for w in tagger(text)]
pipe = Pipeline([
    ('tfidf', TfidfVectorizer(tokenizer=tok, token_pattern=None)),
    ('lr', LogisticRegression(max_iter=1000)),
])
pipe.fit(texts_train, labels_train)
print(pipe.score(texts_test, labels_test))
Q2. 同じデータで BERT を fine-tune し、 性能を比較しなさい。

Hugging Face Trainer を使い、 bert-base-japanese-v3 を 3 エポック程度学習。 GPU が必要。

Q3. SBERT で 1000 文を埋め込み、 k-means でクラスタリング、 各クラスタを命名しなさい。
1
2
3
4
5
from sentence_transformers import SentenceTransformer
from sklearn.cluster import KMeans
model = SentenceTransformer('intfloat/multilingual-e5-base')
emb = model.encode(texts)
clusters = KMeans(n_clusters=10, n_init=10).fit_predict(emb)

📝 11. 報告フォーマット

❌ NG例

「BERT で文書分類しました。」

✅ OK例

「ネット口コミ 8,000 件(5 段階評価、 不均衡 [40%/25%/15%/12%/8%])を 3 クラス(高/中/低)に集約し、 cl-tohoku/bert-base-japanese-v3 を batch=16, lr=2e-5, 3epoch で fine-tune。 Stratified 5-fold CV で Macro-F1 = 0.78 ± 0.02。 ベースラインの TF-IDF+ロジスティック (Macro-F1 = 0.63) より大幅改善。 アテンション可視化で『否定形』『極性語』に強い注目を確認。 ハイパラ選定は内側 CV で実施した。」

🐍 12. ライブラリ早見表

用途 パッケージ
日本語形態素解析fugashi, mecab-python3, sudachipy, janome
解析パイプspacy, ginza, stanza
古典NLPsklearn.feature_extraction.text, nltk
単語埋め込みgensim, fasttext
事前学習モデルtransformers, sentence-transformers
トークナイザtokenizers, sentencepiece, tiktoken
トピックgensim, bertopic, top2vec
ベクトル検索faiss, chromadb, qdrant, weaviate
LLMフレームlangchain, llamaindex, dspy
評価seqeval, sacrebleu, evaluate (HuggingFace)

📜 13. NLP の歴史

💼 14. 実務応用

✅ 15. NLP プロジェクト チェックリスト

🗾 16. 日本語 NLP 固有の課題と対策

16.1 分かち書きの粒度

16.2 表記揺れ

16.3 主語省略・敬語

日本語は文脈で省略される情報が多い。 BERT 系は文脈学習で対応するが、 完璧ではない。 敬語レベル(タメ口・丁寧語・尊敬語・謙譲語)は文体識別の特徴。

16.4 文字種混在

漢字・ひらがな・カタカナ・英数字が同一文に混在。 サブワード分割が破綻しやすい。 SentencePiece が標準的に使われる理由の一つ。

16.5 縦書き・ルビ・絵文字

古典文書・Web テキストではメタ情報除去が必要。

❓ 17. よくある質問

Q. ChatGPT がある今、 古典的 NLP は不要?

A. ノー。 (1) 小規模・高速・確定的処理ではルール / 線形が依然有用、 (2) LLM の前処理として古典手法が使われる、 (3) コスト・遅延・プライバシー要件で LLM が使えない場面が多い。

Q. 日本語 BERT で使うべきモデルは?

A. 2026 時点では cl-tohoku/bert-base-japanese-v3、 LINE LDLM、 rinna が主要。 ドメイン特化なら継続事前学習を検討。

Q. RAG と Fine-tune、 どちらが良い?

A. 知識更新性が高い・出典が必要 → RAG。 文体・スタイル変更 → Fine-tune。 多くは両者の併用。

Q. LLM のハルシネーションをどう防ぐ?

A. 完全に防ぐのは困難。 (1) RAG で根拠付け、 (2) Self-Consistency や別モデルでの検証、 (3) 出力の確信度を測定、 (4) 重要な決定では人間がレビュー。

✅ 18. 日本語 NLP チェックリスト

📊 19. NLP 評価指標の詳細

BLEU(機械翻訳)

$$\mathrm{BLEU} = \mathrm{BP} \cdot \exp\left(\sum_{n=1}^N w_n \log p_n\right)$$

$p_n$ は n-gram 精度、 $\mathrm{BP}$ は短さペナルティ。 0-1 で大きいほど良い。 単一文では信頼性が低い。

ROUGE(要約)

BERTScore

BERT 埋め込みのコサイン類似度ベース。 BLEU/ROUGE より人手評価との相関が高い。

$$\mathrm{BERTScore} = \frac{1}{|x|}\sum_{x_i} \max_{\hat{x}_j} \cos(\mathbf{e}_{x_i}, \mathbf{e}_{\hat{x}_j})$$

perplexity(言語モデル)

$$\mathrm{PPL} = \exp\left(-\frac{1}{N}\sum_i \log p(x_i | x_{

「次の単語をどれくらい予測しにくいか」。 小さいほど良い言語モデル。

NER の評価

エンティティ単位の P/R/F1(部分一致でなく完全一致)。 seqeval ライブラリが標準。

🔍 20. RAG(検索拡張生成)のパターン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from sentence_transformers import SentenceTransformer
import faiss
import numpy as np

# 1. インデックス構築
embedder = SentenceTransformer('intfloat/multilingual-e5-base')
docs = ['文書1...', '文書2...', ...]
embeddings = embedder.encode([f'passage: {d}' for d in docs])
index = faiss.IndexFlatIP(embeddings.shape[1])
faiss.normalize_L2(embeddings)
index.add(embeddings)

# 2. クエリ → 検索
query = '東京の人口は?'
q_emb = embedder.encode([f'query: {query}'])
faiss.normalize_L2(q_emb)
scores, idx = index.search(q_emb, k=5)
retrieved = [docs[i] for i in idx[0]]

# 3. LLM に注入
prompt = f"""以下の文書を参考に質問に答えてください。

文書:
{chr(10).join(retrieved)}

質問: {query}
回答:"""

🏢 21. ドメイン別 NLP 応用

21.1 法務・契約 NLP

21.2 医療 NLP

21.3 金融 NLP

21.4 政府・公共

🔖 キーワード索引(補強)

主要モデル・タスク・指標・前処理用語を一覧で。 各チップから関連セクションへジャンプできます。

TF-IDF Word2Vec BERT/SBERT NER LDA BLEU QA RAG プロンプト 埋め込み コサイン類似度 Attention Transformer SentencePiece MeCab fugashi spaCy Hugging Face LangChain LoRA PEFT 分散表現 Tokenizer BPE

🧮 SSDSE-B-2026 で「テキスト風」データを扱う実値計算例

SSDSE-B-2026 自体は数値データですが、 都道府県名と都道府県の特徴量を「擬似的なテキストドキュメント」として扱う実例を示します(教育目的)。

例:都道府県名を「文書」として TF-IDF と BoW を作る

各都道府県の県庁所在地名や地理キーワードを文字列として連結し、 TF-IDF 行列を作成して類似都道府県を求めます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)

# 各都道府県の特徴を「テキスト化」(数値→文字列の擬似ドキュメント)
docs = []
for _, row in df.iterrows():
    pref = str(row['都道府県'])
    # 各列を「項目名_値帯」の形式に変換(例:'人口_多', '高齢化率_高')
    tokens = [pref]
    docs.append(' '.join(tokens))

# 実テキスト例:県庁所在地と地域情報
labels = df['都道府県'].tolist()
texts = [f"{name} 県庁 地方 統計 経済 人口" for name in labels]

vectorizer = TfidfVectorizer(analyzer='char_wb', ngram_range=(2,3))
X = vectorizer.fit_transform(texts)
print('TF-IDF 行列の形:', X.shape)

# コサイン類似度で似た県を探す
sim = cosine_similarity(X)
print(f'東京と大阪の類似度: {sim[12, 26]:.3f}')

例:都道府県名から文字 n-gram を抽出

n-gram は文字列分類のベースライン。 47都道府県名を文字バイグラム化すれば、 似た音韻を持つ県名がベクトル空間で近くなります。

1
2
3
4
5
6
7
from sklearn.feature_extraction.text import CountVectorizer

prefs = df['都道府県'].tolist()  # 47県名
cv = CountVectorizer(analyzer='char', ngram_range=(2,2))
bigram_mat = cv.fit_transform(prefs)
print('バイグラム種類数:', len(cv.vocabulary_))
print('「岡」を含む県:', [p for p in prefs if '岡' in p])

本格的なテキストデータと組み合わせる場合

SSDSE 単体ではテキスト分析の練習が難しいため、 以下のような外部公的テキストデータと組み合わせることを推奨:

⚠️ NLP の落とし穴(補強・各 100 文字以上)

① 「BERT が最強」と思い込んで古典手法を捨てる
小データ・高速応答が必要な場面では、 TF-IDF + ロジスティック回帰や LightGBM のほうが BERT より精度も推論速度も上回ることが多い。 BERT は通常 GPU と 100MB 級モデルが必要で、 月10万件規模の API 課金や応答遅延(数百ms)が問題化する。 まずベースラインで TF-IDF を試してから、 必要に応じて BERT を検討するのが鉄則。
② 日本語に英語向けトークナイザを使い精度激減
英語 BERT の subword tokenizer(WordPiece, BPE)に日本語をそのまま流すと、 「私は学生です」が「私_は_学_生_で_す」のように文字単位で分割され、 意味的な単位が失われる。 必ず日本語事前学習モデル(cl-tohoku/bert-base-japanese, rinna 系等)と対応する tokenizer をセットで使う。 fugashi+ipadic や Sudachi の辞書差にも注意。
③ ストップワード除去を BERT 系にも適用してしまう
古典手法(BoW, TF-IDF)ではストップワード除去が有効だが、 BERT 等の文脈モデルでは「は」「が」「を」など助詞こそ意味を担う重要トークン。 これを除去すると文法構造が壊れて精度が大きく落ちる。 「前処理は手法依存」と理解し、 古典は積極的に前処理・BERT 系は原文に近い形で投入するのが基本。
④ 学習データと評価データに時系列リークがある
ニュース記事の感情分析やレビュー分類でランダム分割すると、 訓練データに「未来のイベント」が含まれて評価データを予測することになり、 実運用で精度が激減する。 時系列ベースのデータでは必ず時間で前後分割し、 「過去 → 未来」を予測する形にする。 また、 同じ著者・同じスレッドが train/test 双方に出ない author-aware split も検討。
⑤ LLM のハルシネーションをそのまま信用する
ChatGPT や Claude などの LLM は「もっともらしい嘘」を返すことがある(hallucination)。 特に固有名詞・日付・統計値・引用文献は誤りが多い。 業務利用では必ず RAG で外部知識を参照させ、 出典 URL を出力に含め、 人間がチェックできる仕組みにする。 法務・医療など重大領域では LLM 単独の判定を絶対に最終判断にしない。
⑥ BLEU だけで翻訳・要約品質を評価する
BLEU は n-gram の一致率で、 意味的に正しいが表現が異なる訳文を低く評価してしまう。 「実は意味は同じ」翻訳が BLEU=0.2 で「逐語訳で破綻」翻訳が BLEU=0.5 のような逆転が起きる。 現在は BERTScore, COMET, chrF++ などの意味ベースの指標と人手評価(adequacy / fluency)を併用するのが標準。
⑦ 小データで巨大 LLM を全パラメータ fine-tune
70億パラメータ級の LLM を 1000件のデータで全パラメータ微調整すると、 ほぼ確実に過学習し汎化性能を失う。 さらに数十 GB の GPU と数時間〜数日の計算時間が必要でコストも高い。 小データには LoRA・QLoRA・Prefix Tuning などの PEFT(Parameter-Efficient Fine-Tuning)か、 Few-shot prompting で対応するのが現代の常識。

🐍 Python 実装バリエーション(scikit-learn / scipy / Hugging Face)

1. scikit-learn — TF-IDF + ロジスティック回帰(古典ベースライン)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

texts = ['東京は首都です', '大阪は商業の街', '京都は古い都', '横浜は港町']
labels = [1, 0, 1, 0]

pipe = Pipeline([
    ('tfidf', TfidfVectorizer(analyzer='char_wb', ngram_range=(2,3))),
    ('clf', LogisticRegression(max_iter=1000))
])
scores = cross_val_score(pipe, texts, labels, cv=2)
print(f'CV 平均: {scores.mean():.3f}')

2. scipy — コサイン類似度・統計量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from scipy.spatial.distance import cosine, cdist
from scipy import sparse
import numpy as np

# 文書ベクトル(疎ベクトル)
v1 = np.array([1, 2, 0, 3, 0])
v2 = np.array([0, 1, 2, 1, 1])

# scipy.spatial.distance.cosine は距離(1-類似度)
dist = cosine(v1, v2)
print(f'コサイン類似度: {1 - dist:.3f}')

# 多文書一括の類似度行列
docs = np.random.RandomState(0).rand(10, 50)  # 例示用(実データに置換)
sim_matrix = 1 - cdist(docs, docs, metric='cosine')

3. Hugging Face transformers — BERT で文ベクトル化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from transformers import AutoTokenizer, AutoModel
import torch

tokenizer = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v3')
model = AutoModel.from_pretrained('cl-tohoku/bert-base-japanese-v3')

texts = ['東京は日本の首都です', '大阪は商業の中心地']
inputs = tokenizer(texts, padding=True, return_tensors='pt')
with torch.no_grad():
    outputs = model(**inputs)
# [CLS] トークンの出力を文ベクトルとして使う
sent_vec = outputs.last_hidden_state[:, 0, :]
print('文ベクトル形:', sent_vec.shape)

4. sentence-transformers — お手軽 SBERT

1
2
3
4
5
6
7
8
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity

model = SentenceTransformer('intfloat/multilingual-e5-small')
sentences = ['今日は天気が良い', '本日は晴天です', '株価が下落した']
embs = model.encode(sentences)
sim = cosine_similarity(embs)
print(sim)

5. gensim — Word2Vec / LDA

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from gensim.models import Word2Vec, LdaModel
from gensim.corpora import Dictionary

# tokens は分かち書き済みの list of list
tokens = [['東京', 'は', '日本', 'の', '首都'], ['大阪', 'は', '商業', 'の', '街']]
w2v = Word2Vec(tokens, vector_size=50, min_count=1, window=3, epochs=10)
print('東京の近傍:', w2v.wv.most_similar('東京', topn=3))

dic = Dictionary(tokens)
corpus = [dic.doc2bow(t) for t in tokens]
lda = LdaModel(corpus, num_topics=2, id2word=dic, passes=5)
for tid, w in lda.print_topics():
    print(tid, w)

6. spaCy + GiNZA — 日本語の依存構造解析

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import spacy

nlp = spacy.load('ja_ginza')
doc = nlp('東京は日本の首都です。大阪は商業の中心地です。')

for sent in doc.sents:
    for tok in sent:
        print(tok.text, tok.lemma_, tok.pos_, tok.dep_)

# 固有表現抽出
for ent in doc.ents:
    print(ent.text, ent.label_)