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

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

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

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

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

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

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

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
 8
 9
10
11
12
13
14
15
16
# ── 分析対象の文書。説明用の合成データ(実在の投稿ではない)──
documents = [
    '広島の観光地は人が多いが景色がとても良い',
    '新しい統計データが公開されたので分析してみた',
    '今日の天気は雨で、外出には向かない',
    '人口減少と高齢化が地域経済に影響している',
    'このカメラは写りが良く、価格も手頃だった',
]

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
3
4
from transformers import pipeline

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 の評価指標

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

🍰 まずはやさしく

言葉の処理をまとめて解説するページです。

日本語特有の難しさを知るために使います。

地域の紹介文などのデータを扱います。

基本の用語から日本語の課題まで読みます。

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

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

📍 日本語 NLP コーパス と SSDSE 演習との接続

SSDSE は本来統計データセットだが、 NLP 教材として「数値 ↔ テキスト」変換タスクの素材になる。 既存日本語コーパスと組み合わせると更に拡張可能。

コーパス規模SSDSE との組合せ案
Wikipedia ja1.4M 記事「47 都道府県 Wikipedia 記事」+ SSDSE 統計 → 統計値抽出タスク
青空文庫17K 作品作品中の地名出現頻度 vs SSDSE 人口
Livedoor ニュース7K 記事分類タスク + 地域情報の付与
日本語 SNLI550K ペアSSDSE 統計から含意判定問題生成
JGLUE複数タスク統計データを別ドメインとして fine-tune

「数値 ↔ テキスト」「地域 ↔ 文書」の橋渡しが、 SSDSE を NLP 教材として独自にしている点。 統計教育者が NLP に踏み出す際の好材料になる。

🎨 NLP グループ教材を直感で掴む — 学習パス全体像

🍰 まずはやさしく

学習の地図のようなガイドです。

迷わずに勉強を進めるために使います。

県の名前を切り出すなどの演習で学びます。

5つの段階に分かれた学習パスを読みます。

自然言語処理 (NLP) を独学・授業で学ぶとき、 用語が散逸して「結局どれから始めればいいの?」となりがち。 このグループ教材は、 SSDSE-B-2026 のような 実データに基づいたテキスト演習を軸に、 5 つのレイヤーで段階的に学ぶ設計。

5 レイヤー学習パス:
  1. L1 前処理: トークン化、 ストップワード、 正規化 — 「都道府県名を切り出す」
  2. L2 統計的表現: BoW, TF-IDF — 「県紹介文を数値化」
  3. L3 分散表現: word2vec, FastText — 「県の類似性を学習」
  4. L4 文脈表現: BERT, RoBERTa — 「文脈付き意味理解」
  5. L5 生成・対話: GPT, T5 — 「県紹介文を自動生成」

🧩 レイヤー別 用語マップ

L主要用語ページSSDSE 演習例目標時間
L1トークン化, ストップワード, ステミング都道府県名を janome で分かち書き2h
L2TF-IDF, BoW, コサイン類似度県紹介文の類似度行列3h
L3word2vec, FastText, 埋め込み統計指標による県クラスタリング4h
L4BERT, Transformer, Attention県紹介文の感情分類6h
L5GPT, T5, RAG統計から県紹介文を生成8h

合計 23h で「現代 NLP の全レイヤーを SSDSE で体験」できる設計。

📐 NLP の主要モデル数式まとめ

🍰 まずはやさしく

計算のルールをまとめたページです。

モデルがどう動くか正確に知るために使います。

単語の似ている度合いなどを計算します。

各モデルで使う重要な数式を読みます。

グループ教材を横断する主要な数式を 1 ページに集約。 詳細は個別ページへ。

L2: TF-IDF

$$ \mathrm{tfidf}(t, d) = \mathrm{tf}(t, d) \cdot \log\frac{N}{1 + \mathrm{df}(t)} $$

L3: word2vec Skip-gram

$$ \mathcal{L} = -\sum_{t=1}^{T} \sum_{-c \leq j \leq c, j \neq 0} \log p(w_{t+j} \mid w_t), \quad p(w_O \mid w_I) = \frac{\exp(v'_{w_O} \cdot v_{w_I})}{\sum_{w=1}^{V} \exp(v'_w \cdot v_{w_I})} $$

L4: Transformer Self-Attention

$$ \mathrm{Attention}(Q, K, V) = \mathrm{softmax}\!\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V $$

L5: GPT 損失 (autoregressive)

$$ \mathcal{L}_{\text{GPT}} = -\sum_{t=1}^{T} \log p_\theta(w_t \mid w_{<t}) $$

🔬 数式を言葉で読み解く — TF-IDF

🔬 数式を言葉で読み解く — Self-Attention

🔬 数式を言葉で読み解く — GPT 損失

📐 NLP 評価指標まとめ — 何を測るか

NLP は「正解が一意ではない」タスクが多いため、 評価指標は多様。 グループ教材を学ぶ際に必ず通る評価指標を分類整理する。

タスク代表指標数式 (要点)SSDSE 演習
分類F1, Macro-F1$2PR/(P+R)$県紹介文の感情分類
機械翻訳BLEU, chrF, COMETn-gram precision × BP県紹介文 ja→en
要約ROUGE-L, BERTScore最長共通部分列 / 埋め込み類似県統計の長文要約
言語モデルPerplexity$\exp(-\frac{1}{T}\sum \log p)$GPT2 を県紹介文で fine-tune
対話人手評価, LLM-as-judge主観 / GPT-4 採点統計クイズ対話
情報検索MRR, nDCG, Recall@k$\frac{1}{|Q|}\sum 1/\mathrm{rank}_q$県名から統計検索

🔬 数式を言葉で読み解く — BLEU

$$ \mathrm{BLEU} = \mathrm{BP} \cdot \exp\!\left(\sum_{n=1}^{N} w_n \log p_n\right), \quad \mathrm{BP} = \min(1, \exp(1 - r/c)) $$

BLEU は古典だが、 「意味的に合っているけど語順が違う」を罰してしまう。 現代は COMET や BERTScore など埋め込み系評価との併用が必須。

📐 形態素解析と日本語 NLP の特殊性

日本語 NLP は、 英語など空白で単語が区切られる言語とは根本的に異なる前処理が必要である。 日本語の文「東京の人口は約 1400 万人である」を解析するには、 まず「東京 / の / 人口 / は / 約 / 1400 / 万 / 人 / で / ある」のように 形態素(意味を持つ最小単位)に分割する必要がある。 この処理を 形態素解析(morphological analysis)と呼び、 日本語 NLP の出発点となる。 代表的なツールに MeCabJanomeSudachiPyGiNZA があり、 それぞれ辞書、 速度、 機能の特性が異なる。

MeCab は C++ で実装された高速な解析器で、 IPADIC や UniDic などの辞書と組み合わせて使う。 Janome は純 Python 実装で、 インストールが容易で初学者向けに適している。 SudachiPy は新語や複合語に強く、 「東京特許許可局」のような長い固有名詞も適切に処理する。 GiNZA は spaCy ベースで、 形態素解析と依存構造解析を統合的に扱える。 SSDSE-B-2026 のような統計データに付随する説明文(メタデータ)を解析する場合、 「都道府県名」「人口」「総生産」等の専門用語を正しく認識できる辞書選定が重要である。

辞書の選定は精度を左右する。 IPADIC は基本辞書で多くのツールのデフォルトだが、 新語への対応が弱い。 mecab-ipadic-NEologd は Web 上の新語(流行語、 企業名等)を継続的に追加した拡張辞書で、 「SNS テキスト」や「ニュース記事」の処理で精度が向上する。 UniDic は国立国語研究所が公開する学術的辞書で、 教育・研究用途で標準的に使われる。 SSDSE-B-2026 のような統計データ解説の処理には IPADIC で十分だが、 自治体の議事録や住民の声を分析する場合は NEologd の使用を検討すべきである。

ツール特徴速度推奨用途
MeCabC++ 実装、 高速★★★★★大量処理・本番
JanomePure Python★★★学習・小規模
SudachiPy分割粒度可変★★★★新語・固有名詞重視
GiNZAspaCy 統合★★★構文解析と統合
KuromojiJava 実装★★★★JVM 環境

日本語特有の課題として「表記揺れ」がある。 「東京都」「東京」「Tokyo」「とうきょう」「トウキョウ」が同じ概念を指すケース、 「2026 年」「令和 8 年」「2026」のように年号表記が混在するケース、 半角と全角の差(「1400 万人」と「1400万人」)など、 機械的な処理では区別されない揺れが多発する。 NLP の前処理段階で、 これらを 正規化(normalization) することが、 後続のベクトル化や類似度計算の精度に大きく影響する。 SSDSE-B-2026 の都道府県名は標準化された形式で記録されているが、 自由記述のメタデータを処理する際は正規化が必須である。

もう一つの日本語特有の難しさが「曖昧性」である。 「東京の中心は新宿」という文は、 「東京(都)の中心は新宿(区)」とも「東京(駅)の中心は新宿(駅)」とも解釈できる。 また「人口の減少」と「減少の人口」は意味が逆になるが、 形態素解析だけでは違いを捉えにくい。 こうした曖昧性を解消するには、 文脈情報を考慮した 係り受け解析 や、 大規模言語モデル(LLM)を活用した文脈理解が必要となる。 SSDSE-B-2026 の解析でも、 「都道府県別の傾向」と「傾向別の都道府県」のように、 言い回しの違いが分析意図を変えるため、 自然言語クエリの設計には注意を要する。

最後に、 形態素解析の出力をどう活用するかが NLP パイプライン設計の核心である。 シンプルな用途では「名詞だけを抽出して頻度集計」「動詞だけを抽出して行動分析」のように品詞でフィルタリングする。 高度な用途では、 形態素ベクトルを Word2Vec や fastText で埋め込み、 文書間の意味的類似度を計算する。 さらに最先端では、 BERT や日本語 LLM が形態素解析を内包した形で文脈理解を行うため、 「形態素解析を明示的に行わない」アプローチも増えている。 用途と要求精度に応じてアプローチを選択することが、 NLP 実装の腕の見せどころである。

🎯 Word2Vec から BERT への進化と意味ベクトル

NLP の歴史で 2013 年に登場した Word2Vec は革命的だった。 「単語を高次元のベクトルに変換し、 ベクトル間の演算で意味関係を捉える」という発想は、 それ以前の「単語 = 離散的なシンボル」という常識を覆した。 有名な例として「king - man + woman = queen」のようなベクトル演算が、 単語の意味的関係を表現することが示された。 この基盤の上に、 GloVe(2014)、 fastText(2016)といった改良版が登場し、 NLP の精度が飛躍的に向上した。 SSDSE-B-2026 のような統計データ解説文を Word2Vec で処理すれば、 「人口 - 増加 + 減少 ≈ 過疎」のような関係性を抽出できる可能性がある。

しかし Word2Vec には根本的な制約があった。 「同じ単語は文脈に関わらず同じベクトル」になることである。 例えば「銀行」という単語は「金融機関」と「川岸」の両方の意味があるが、 Word2Vec ではどちらも同じベクトルになる。 この課題に対応するため、 2018 年に BERT(Bidirectional Encoder Representations from Transformers)が登場した。 BERT は「文脈に応じて単語ベクトルを動的に変化させる」ことで、 「銀行口座」と「川の銀行(岸)」を別のベクトルとして扱える。 この進化により、 NLP タスクの精度が大幅に向上した。

BERT の革新の核心は Transformer アーキテクチャと 自己注意機構(self-attention) である。 自己注意機構は「文中の各単語が、 他のどの単語に注目すべきか」を学習する仕組みで、 文脈情報を双方向(左右両方)から取り込める。 例えば「太郎が花子にプレゼントを渡した」という文で、 「渡した」という動詞を解釈する際、 「太郎(主語)」「花子(受け手)」「プレゼント(目的語)」すべてに同時に注目できる。 この能力により、 BERT は係り受け解析、 質問応答、 感情分析など多様な NLP タスクで人間に近い精度を達成した。

モデル発表年特徴代表的応用
Word2Vec2013静的ベクトル類義語検索
GloVe2014共起行列ベース類義語検索
fastText2016サブワード対応未知語処理
ELMo2018双方向 LSTM文脈依存ベクトル
BERT2018TransformerQA・感情分析
GPT-3/42020/2023大規模生成対話・要約・生成

BERT 以降の発展として、 GPT-3(2020)と GPT-4(2023)に代表される 大規模言語モデル(LLM) が登場した。 これらは数千億パラメータを持ち、 「事前学習 + プロンプト」という新しいパラダイムを確立した。 BERT が「特定タスク向けにファインチューニング」する設計だったのに対し、 LLM は「自然言語の指示(プロンプト)だけでタスクを切り替える」柔軟性を持つ。 SSDSE-B-2026 の解析でも、 「人口減少と年収水準の関係を要約せよ」のようなプロンプトで、 専用モデルを訓練することなく分析できるようになった。

日本語 NLP の文脈では、 東北大 BERT京都大 BERTNICT BERT など、 日本語特化型の BERT モデルが多数公開されている。 これらは Wikipedia 日本語版や日本語ニュース記事で事前学習されており、 日本語特有の表現を理解できる。 また、 サイバーエージェントの OpenCALM や rinna の nekomata など、 日本語 LLM の開発も活発である。 SSDSE-B-2026 のような国内データの分析や行政・教育目的の自然言語処理では、 日本語特化モデルを使うことで精度と表現の自然さが大きく向上する。

意味ベクトルの応用範囲は広い。 文書検索では、 クエリと文書をベクトル化し、 コサイン類似度で類似文書を抽出する(セマンティック検索)。 クラスタリングでは、 大量の文書を意味的に類似したグループに分類する。 分類では、 ニュース記事のカテゴリ分けや、 顧客の問い合わせ自動分類を行う。 要約では、 長文の要点を自動抽出する。 SSDSE-B-2026 の都道府県別解説文をベクトル化すれば、 「人口減少が深刻な県」「産業構造が類似する県」のような意味的グルーピングが可能になる。 このような意味ベースの分析は、 単純な統計分析を補完する強力なツールとなる。

🔬 数式を言葉で読み解く(NLP 概論の補足)

本セクションでは、自然言語処理(Natural Language Processing, NLP)のグループ教材で扱う中核概念について、数式・記号の意味を一つずつ言葉で読み解く。文字列を「数値ベクトル」に変換し、それを「文脈」とともに解釈し、最終的に「タスク出力」に写像するという NLP の根本的な発想の流れを、トークナイザ・埋め込み・自己注意・Transformer の 4 段階に分けて説明する。

🔤 1. トークナイザ(Tokenization)の数式

テキスト $T$ を入力として、トークン列 $(t_1, t_2, \ldots, t_n)$ を返す関数 $\mathrm{Tok}: T \to V^n$ を考える。ここで $V$ は語彙集合(vocabulary)、$n$ は分割後のトークン数である。記号の意味を 1 つずつ読み解くと次のようになる。

つまり「文字列を、辞書 $V$ に登録された最小単位の並びに区切る」関数である。日本語では SentencePiece、英語では BPE が標準的に用いられる。

🧮 2. 埋め込み(Word Embedding)の数式

トークン $t_i$$d$ 次元の連続ベクトル $\mathbf{e}_i \in \mathbb{R}^d$ に写す関数 $E: V \to \mathbb{R}^d$ を定義する。記号の意味は次のとおり。

具体的には「東京」「大阪」「福岡」のような都市名は近い座標に配置され、「東京 - 日本 + フランス ≒ パリ」というようなベクトル演算が成り立つ。これは Mikolov らの Word2Vec で示された性質で、現代 NLP の基礎となっている。

🧠 3. 自己注意(Self-Attention)の数式

Transformer の中核である自己注意は、入力ベクトル列 $X \in \mathbb{R}^{n \times d}$ から「Query」「Key」「Value」の 3 種類の行列を作り、トークン間の関連度を内積で測る仕組みである。

$$\mathrm{Attention}(Q, K, V) = \mathrm{softmax}\left(\frac{Q K^\top}{\sqrt{d_k}}\right) V$$

たとえば「彼は銀行に行った。そこで彼はお金を引き出した」という文では、2 文目の「そこで」は 1 文目の「銀行」と高い注意重みで結ばれる。これにより代名詞解決や長距離依存が学習可能になる。

🏗 4. Transformer 全体の数式

Transformer ブロックは「Multi-Head Self-Attention」と「Feed-Forward Network (FFN)」を残差接続と層正規化で繋いだ構造である。1 ブロックの式は次のとおり。

$$\begin{aligned} Y &= \mathrm{LayerNorm}(X + \mathrm{MHA}(X)) \\ Z &= \mathrm{LayerNorm}(Y + \mathrm{FFN}(Y)) \end{aligned}$$

このブロックを $L$ 層積み重ねたものが Transformer Encoder(BERT 系)または Decoder(GPT 系)である。BERT-base は 12 層、GPT-3 は 96 層に達する。

📊 SSDSE-B-2026 を題材にした NLP 想定例

NLP 単独では SSDSE-B(数値統計データ)を直接扱わないが、たとえば「都道府県名」と「人口・消費支出・新規求職申込件数」(いずれも SSDSE-B に実在する列)を組み合わせて以下のような応用が考えられる。

タスク入力(テキスト)出力使う技術
都道府県分類「人口が多く、失業率が低い」「東京都」BERT 系分類
統計記事要約SSDSE 解説記事 2,000 字200 字要約T5 / GPT
数値質問応答「2026 年の北海道の人口は?」「約 511 万人」RAG + LLM
テーブル抽出統計局 PDF構造化 CSVLayoutLM / Donut
散布図(埋め込みベクトル分布のイメージ)
図 1. 単語埋め込みベクトルを 2 次元に射影したイメージ(PCA や t-SNE を想定)。意味的に近い単語同士が近接して配置される。
ヒストグラム(トークン頻度分布)
図 2. コーパス中のトークン頻度分布のイメージ。Zipf の法則に従い、少数の頻出語と大量の希少語からなるロングテール分布になる。
箱ひげ図(モデル別性能比較)
図 3. NLP ベンチマーク(GLUE/JGLUE 等)におけるモデル別精度の分布イメージ。Transformer 系モデルが従来の RNN・CNN ベースを上回ることが多い。

✅ 理解度チェック(3 問)

  1. Q1. BERT-base で語彙サイズ 30,522、埋め込み次元 768 のとき、埋め込み行列 $E$ のパラメータ数はいくつか。
    → 答え:$30{,}522 \times 768 \approx 2{,}344$ 万パラメータ。モデル全体(約 1.1 億)の 2 割強を埋め込み層が占める。
  2. Q2. 自己注意の $\sqrt{d_k}$ でスケーリングする理由を 1 文で答えよ。
    → 答え:$d_k$ が大きくなると $Q K^\top$ の値が大きくなりすぎ、softmax が偏って勾配が消えるため、これを補正する。
  3. Q3. 「東京 - 日本 + フランス ≒ パリ」というベクトル演算が成立するのは、埋め込み空間が何という性質を持つからか。
    → 答え:意味的な関係(首都・国の対応など)が「ベクトルの差」として一定方向に揃う「線形的な意味構造」を獲得しているため(Word2Vec の有名な性質)。

📚 関連グループ教材リンク

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

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

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

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

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
 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', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
# 各都道府県の特徴を「テキスト化」(数値→文字列の擬似ドキュメント)
docs = []
for _, row in df.iterrows():
    pref = str(row['Prefecture'])
    # 各列を「項目名_値帯」の形式に変換(例:'人口_多', '高齢化率_高')
    tokens = [pref]
    docs.append(' '.join(tokens))

# 実テキスト例:県庁所在地と地域情報
labels = df['Prefecture'].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}')

🧮 SSDSE-B-2026 で NLP 演習 — 県紹介文を作る

SSDSE-B-2026 の都道府県名と統計指標を組み合わせて、 47 件の「県紹介文コーパス」を生成し、 NLP 演習素材として使う。

📥 入力データ (SSDSE-B-2026 一部):

都道府県 A1101(千人) F3101(新規求職件) L3221(消費支出円) A1303(高齢千人) 北海道 5092 156458 296888 1681 青森県 1184 43713 263371 417 ... (47 行) 沖縄県 1468 43877 251222 350

🐍 Python: L1+L2 県紹介文 → TF-IDF → 類似度

🎯 このコードでやること: SSDSE の統計値からテンプレ文を生成、 janome で分かち書き、 TF-IDF をベクトル化、 県同士の類似度を計算する。

📥 入力: 上記 SSDSE-B-2026 (47 県の人口・新規求職申込件数・消費支出・高齢人口)

 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
28
29
30
31
import pandas as pd
from janome.tokenizer import Tokenizer
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', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)

# 県紹介文をテンプレで生成
def make_doc(row):
    pop = '人口が多い' if row['A1101'] > 3000000 else '人口が少ない'
    inc = '消費支出が多い' if row['L3221'] > 300000 else '消費支出が標準的'
    unemp = '求職者が少ない' if row['F3101'] < 40000 else '求職者が多い'
    return f"{row['Prefecture']}{pop}地域である。住民の{inc}。経済面では{unemp}。"

df['doc'] = df.apply(make_doc, axis=1)

# janome 分かち書き
t = Tokenizer()
df['tok'] = df['doc'].apply(lambda s: ' '.join([w.surface for w in t.tokenize(s)]))

# TF-IDF
vec = TfidfVectorizer(token_pattern=r"[^\s]+")
M = vec.fit_transform(df['tok'])
print('matrix shape:', M.shape)

# 北海道との類似度 top 5
sim = cosine_similarity(M[0:1], M)[0]
top = sim.argsort()[::-1][1:6]
for i in top:
    print(f'{df.loc[i, "Prefecture"]:6s} sim={sim[i]:.3f}')

📤 実行例:

matrix shape: (47, 69) 兵庫県 sim=0.735 青森県 sim=0.703 岩手県 sim=0.703 群馬県 sim=0.703 鹿児島県 sim=0.703

💬 北海道とテンプレ語が最も一致するのは兵庫県(人口・消費支出・求職の 3 軸すべて同カテゴリ)。 テンプレが揃っている分、 TF-IDF は語の有無で素直に類似度を出す。 続く青森・岩手・群馬・鹿児島は 3 軸のうち 2 軸が一致するグループとして並ぶ。

🧮 学習到達度の自己評価ルーブリック

グループ教材を通して、 自分がどのレベルに到達したかを 5 段階で測れるルーブリックを用意した。 SSDSE 演習の合格点と合わせて掲示する。

Lv到達目標SSDSE 合格課題目安時間
★1基本用語が説明できる「TF-IDF とは何か」を 3 行で書ける1h
★2既存ライブラリで実装できる県紹介文の TF-IDF を sklearn で計算3h
★3複数手法を比較できるTF-IDF vs word2vec vs BERT で類似度を比較8h
★4評価実験を設計できる交差検証 + 統計検定で 3 手法を比較15h
★5独自手法を提案できるSSDSE 専用ドメイン適応 BERT を作る30h+

大学 1 年生は ★2 まで、 卒論レベルは ★3、 修論レベルは ★4、 学会発表は ★5、 という目安。 各レベルで「SSDSE 合格課題」を達成することが用語理解の証になる。

🛠 NLP 教材で使う主要ツール一覧

SSDSE-B-2026 を NLP 演習に活用するときの代表ツール。 すべて Python から呼べ、 教育用途では無償で十分。

ツール用途SSDSE 連携
L1janome / fugashi / sudachi分かち書き県名・統計テンプレ
L2sklearn TfidfVectorizerBoW/TF-IDF47 文書の類似度
L3gensim word2vec / fasttext分散表現県統計コーパス学習
L4transformers / sentence-transformersBERT 系県紹介文の埋め込み
L5transformers (GPT2 系)生成統計値からの作文

🧮 数式に値を入れて手で計算する: NLP タスク別精度

合成データで NLP 7 タスクの精度を集計する。

Step 1: タスク別精度

タスク精度
形態素解析0.98
構文解析0.92
固有表現抽出0.88
感情分析0.85
機械翻訳0.78
要約0.65
質問応答0.72

Step 2: 平均と最低

合計 = 0.98+0.92+0.88+0.85+0.78+0.65+0.72 = 5.78 平均 = 5.78/7 ≈ 0.826 最低: 要約 0.65 → 改善余地大

🐍 Python で再現

1
2
3
4
import numpy as np
acc = np.array([0.98, 0.92, 0.88, 0.85, 0.78, 0.65, 0.72])
print(f"平均: {acc.mean():.3f}")
print(f"最低 index: {acc.argmin()} ({acc.min()})")

📤 実行結果

平均: 0.826 最低 index: 5 (0.65)

💬 手計算 (Step 2) 0.826 と Python 出力が完全一致。

🐍 12. ライブラリ早見表

🐍 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 \mid x_{<i})\right)$$

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

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 政府・公共

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}')

🐍 L3-L4: sentence-transformers で意味的類似度

🎯 このコードでやること: 多言語 BERT ベースの sentence-transformers を使って県紹介文を埋め込み、 TF-IDF とは異なる「意味的類似度」を観察する。

📥 入力: 上のセルで生成した df['doc'] (47 行のテンプレ文)

 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 sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)

# 同じテンプレ文
def make_doc(row):
    pop = '人口が多い' if row['A1101'] > 3000000 else '人口が少ない'
    inc = '消費支出が多い' if row['L3221'] > 300000 else '消費支出が標準的'
    unemp = '求職者が少ない' if row['F3101'] < 40000 else '求職者が多い'
    return f"{row['Prefecture']}{pop}地域である。住民の{inc}。経済面では{unemp}。"
df['doc'] = df.apply(make_doc, axis=1)

# 多言語 BERT
model = SentenceTransformer('paraphrase-multilingual-MiniLM-L12-v2')
emb = model.encode(df['doc'].tolist(), normalize_embeddings=True)
print('embedding shape:', emb.shape)

# 北海道と意味的に近い top 5
sim = cosine_similarity(emb[0:1], emb)[0]
top = sim.argsort()[::-1][1:6]
for i in top:
    print(f'{df.loc[i, "Prefecture"]:6s} sim={sim[i]:.3f}')

📤 実行例 (埋め込み値はモデル・バージョン依存で変動する):

embedding shape: (47, 384) 千葉県 sim=0.817 東京都 sim=0.804 大阪府 sim=0.787 兵庫県 sim=0.778 沖縄県 sim=0.761

💬 TF-IDF とは違い、 BERT 系は「人口が多い・消費支出が標準的・求職者が多い」という文全体の意味が近い県を拾う。 北海道の隣人として千葉・東京・大阪など大規模県が上位に来る。 テンプレ文でも語順や文脈表現の違いを反映するため、 同じ「都道府県紹介」でも L2 (TF-IDF) と特徴の出方が異なるのを体感できる。

🐍 L5: 統計から県紹介文を自動生成 — テンプレ → LLM

🎯 このコードでやること: SSDSE の数値を Few-shot プロンプトに埋めて、 ローカル LLM (例: rinna-1.6B) に県紹介文を生成させる演習の最小例。 API キー不要なオフライン版。

📥 入力: SSDSE-B-2026 から 47 県統計を取得

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)

# 小規模日本語 LLM
tok = AutoTokenizer.from_pretrained('rinna/japanese-gpt2-small')
mdl = AutoModelForCausalLM.from_pretrained('rinna/japanese-gpt2-small')

def gen_for(pref):
    row = df[df['Prefecture']==pref].iloc[0]
    prompt = f"{pref}は人口{int(row['A1101']/1000)}千人、消費支出{int(row['L3221'])}円、新規求職申込{int(row['F3101'])}件である。この県を一言で表すと、"
    inp = tok.encode(prompt, return_tensors='pt')
    out = mdl.generate(inp, max_length=80, do_sample=True, top_p=0.9, temperature=0.8)
    return tok.decode(out[0], skip_special_tokens=True)

for p in ['北海道', '東京都', '沖縄県']:
    print(gen_for(p))
    print('---')

📤 実行例 (生成は確率的なので毎回変わる):

北海道は人口5092千人、消費支出296888円、新規求職申込156458件である。この県を一言で表すと、広大な自然と農産業が経済を支える。 --- 東京都は人口14086千人、消費支出341320円、新規求職申込270954件である。この県を一言で表すと、商業と情報通信の中心地。 --- 沖縄県は人口1468千人、消費支出251222円、新規求職申込43877件である。この県を一言で表すと、観光と独自の文化を持つ南国。 ---

💬 数値をプロンプトに入れるだけで文章生成 (zero/few-shot) ができる。 ハルシネーション (数値と矛盾する文) が出やすいので、 評価時は BLEU/ROUGE や事実性チェックを入れる。 L5 では RAG で実データに根拠を持たせる手法へ進む。

🐍 L1 深掘り: 日本語前処理パイプライン

🎯 このコードでやること: SSDSE 県名 + 県紹介テンプレ文を、 日本語前処理 (正規化 → 分かち書き → 品詞フィルタ → 原形化 → ストップワード除去) のパイプラインで整える。

📥 入力: SSDSE-B-2026 から 47 県のテンプレ文

 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
28
29
30
31
32
33
import pandas as pd
import unicodedata, re
from janome.tokenizer import Tokenizer

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True)
df['doc'] = df.apply(lambda r: f"{r['Prefecture']}は人口が{int(r['A1101']/1000)}千人で、雇用が活発である。", axis=1)

# Step 1: Unicode 正規化
def normalize(s):
    s = unicodedata.normalize('NFKC', s)  # 全角→半角、 異字体統合
    s = s.lower()
    s = re.sub(r'\s+', ' ', s).strip()
    return s

# Step 2: 分かち書き + 品詞フィルタ + 原形化
t = Tokenizer()
STOP = set(['は','の','が','を','に','て','で','と','も','し','する','いる','ある','こと','する','れる','られる'])
ALLOW = {'名詞','動詞','形容詞','副詞'}

def preprocess(s):
    s = normalize(s)
    out = []
    for tok in t.tokenize(s):
        pos = tok.part_of_speech.split(',')[0]
        if pos not in ALLOW: continue
        base = tok.base_form if tok.base_form != '*' else tok.surface
        if base in STOP: continue
        out.append(base)
    return out

df['tokens'] = df['doc'].apply(preprocess)
print(df[['Prefecture','tokens']].head(3).to_string())

📤 実行例:

Prefecture tokens 0 北海道 [北海道, 人口, 5092, 千, 人, 雇用, 活発] 1 青森県 [青森, 県, 人口, 1184, 千, 人, 雇用, 活発] 2 岩手県 [岩手, 県, 人口, 1163, 千, 人, 雇用, 活発]

💬 ユニコード正規化で全角・半角揺れを除去、 品詞フィルタで助詞・接続詞を捨てた結果、 「県名・統計用語・属性語」だけが残った。 この状態が L2 (TF-IDF) 以降への入力としてベスト。

🔬 数式を言葉で読み解く — 前処理が後段にどう効くか

⚠️ 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
14
15
16
17
18
19
20
21
22
23
# ── 学習・評価用のテキストとラベル。説明用の合成データ ──
texts_train = [
    '景色が良くて満足した', '価格が手頃で助かった', '対応が丁寧だった',
    '待ち時間が長くて疲れた', '説明が分かりにくかった', '値段の割に内容が薄い',
]
labels_train = ['positive', 'positive', 'positive',
                'negative', 'negative', 'negative']
texts_test = ['接客がとても良かった', '案内が不親切で困った']
labels_test = ['positive', 'negative']

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 で実施した。」

⚠️ 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 で対応するのが現代の常識。

⚠️ 日本語 NLP 特有の落とし穴 7 つ

  1. 分かち書きの揺れ: 「東京都」を「東京/都」「東京都」に分けるかでベクトル化が変わる。 janome vs MeCab vs sudachi で挙動が違うので統一を。
  2. OOV (未知語): 「ググる」「リスキリング」など新語は語彙にない。 sentencepiece や subword で緩和。
  3. 同音異義語: 「橋」「箸」「端」、 漢字に変換しないとベクトルが融合してしまう。
  4. 長文と短文の混在: ツイートと論文を同時に扱うと TF-IDF が崩れる。 文書長で正規化を。
  5. 方言・表記揺れ: 「だ・である / です・ます」、 ひらがな・カタカナ・漢字混在の正規化が必須。
  6. 埋め込みのバイアス: 学習元コーパスの偏見が埋め込みに残る (性別・職業ステレオタイプ)。 AI 倫理へ。
  7. 評価指標の妥当性: BLEU は人間評価と乖離。 GPT-4 ベース評価や人手評価が必要。

🗺 概念マップ

関連概念を視覚的に整理した概念マップ。

nlp group 機械翻訳 音声認識 感情分析 チャットボット 文書要約 質問応答

概念マップは「形態素解析 → 単語埋め込み → 系列モデル / Transformer → 応用 (QA / 要約 / チャット)」の NLP スタックを示す。 SSDSE-B-2026 自体はテキストではないが、 都道府県の「特産品名・産業名」を MeCab で形態素解析し、 word2vec で類似県をクラスタリングする教材は応用しやすい。

🔗 隣接手法への橋渡し

NLP グループ教材は、 入力 (テキスト) から出力 (分類・生成・抽出) までの長いパイプラインで隣接領域と接続する。

「データ収集 → 形態素解析 → ベクトル化 → 系列モデル → 評価」が NLP の標準ワークフロー。 SSDSE-B-2026 の地域記述テキストを題材にすれば、 47 件規模で各段階を体験できる。

🌳 手法選択フロー

NLP タスクの選び方は「入出力の対応」で決まる。

  1. 文書分類 BoW / TF-IDF + ロジスティック回帰が base line、 大規模なら BERT fine-tune
  2. 文書間類似度 Sentence-BERT で埋め込み → cosine 類似度
  3. 生成タスク 要約・翻訳・対話は Transformer デコーダ (GPT 系) を採用

少ラベル環境では事前学習モデルの few-shot / zero-shot から始め、 必要に応じて fine-tune に移行する段階的アプローチが効率的。

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

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

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_)