自然言語処理と年号と世界史

### **世界史の年号学習における自然言語処理の活用**  
**「476年 オドアケルが西ローマ帝国を滅ぼす」を数値ベクトル化する手法の提案**  

年号と出来事を関連付けて記憶することは、世界史学習において重要なスキルです。本記事では、**「476年 オドアケルが西ローマ帝国を滅ぼす」** という歴史的な出来事を **自然言語処理（NLP）** を用いて数値ベクトル化する手法を紹介します。  

**TF-IDF, Bag of Words, Word2Vec, FastText, BERT** の各手法を比較し、どのようにして歴史的テキストを数値的に解析できるかを解説します。これにより、年号と出来事を関連付ける数値的感覚を養い、記憶の定着を助ける新たなアプローチを探ります。



## **1. TF-IDF & Bag of Words（BoW）**
**単語の頻度に基づく数値化手法**  

TF-IDF（Term Frequency-Inverse Document Frequency）と Bag of Words（BoW）は、文章内の単語の出現頻度に基づいてベクトルを作成する手法です。  



## **1. TF-IDF & Bag of Words（BoW）**
TF-IDFとBag of Words（BoW）は、テキスト内の単語の出現頻度に基づいてベクトルを作成する手法です。BoWは単語の頻度のみを考慮し、TF-IDFは単語の出現頻度と希少性を加味して重み付けを行います。

### **Pythonコード**
```python
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

# 対象の文章
documents = [
    "オドアケルが西ローマ帝国を滅ぼす",
    "西ローマ帝国は476年に滅亡した",
    "オドアケルは西ローマ帝国最後の皇帝を退位させた",
    "476年にロムルス・アウグストゥルスが退位"
]

# Bag of Words (BoW)
bow_vectorizer = CountVectorizer()
bow_matrix = bow_vectorizer.fit_transform(documents)

# TF-IDF
tfidf_vectorizer = TfidfVectorizer()
tfidf_matrix = tfidf_vectorizer.fit_transform(documents)

# 単語リストの取得
feature_names_bow = bow_vectorizer.get_feature_names_out()
feature_names_tfidf = tfidf_vectorizer.get_feature_names_out()

# Bag of Words の出力
print("=== Bag of Words ===")
print(feature_names_bow)
print(bow_matrix.toarray())

# TF-IDF の出力
print("\n=== TF-IDF ===")
print(feature_names_tfidf)
print(np.round(tfidf_matrix.toarray(), 2))
```

### **解説**
- **BoW**：単語の出現回数をカウントし、各文章をベクトル化。
- **TF-IDF**：頻繁に登場する単語のスコアを下げ、希少な単語の重みを上げる。

---

## **2. Word2Vec & FastText**
Word2VecとFastTextは、単語の意味を数値ベクトルに変換する手法です。Word2Vecは単語単位でベクトル化し、FastTextはサブワード（n-gram）を考慮するため、新しい単語にも対応可能です。

### **Pythonコード**
```python
import gensim
from gensim.models import Word2Vec, FastText
import numpy as np

# 学習用のコーパス（文章のリスト）
sentences = [
    ["476年", "オドアケル", "が", "西ローマ帝国", "を", "滅ぼす"],
    ["西ローマ帝国", "は", "476年", "に", "滅亡", "した"],
    ["オドアケル", "は", "西ローマ帝国", "最後", "の", "皇帝", "を", "退位", "させた"],
    ["476年", "に", "ロムルス・アウグストゥルス", "が", "退位"]
]

# Word2Vec モデルの学習
word2vec_model = Word2Vec(sentences, vector_size=100, window=5, min_count=1, sg=0)

# FastText モデルの学習
fasttext_model = FastText(sentences, vector_size=100, window=5, min_count=1, sg=0)

# 特定の単語のベクトルを取得
word = "476年"
word2vec_vector = word2vec_model.wv[word]
fasttext_vector = fasttext_model.wv[word]

# Word2Vec のベクトルを表示
print(f"=== Word2Vec: {word} のベクトル ===")
print(np.round(word2vec_vector, 4))

# FastText のベクトルを表示
print(f"\n=== FastText: {word} のベクトル ===")
print(np.round(fasttext_vector, 4))

# Word2Vec の類似語を表示
print(f"\n=== Word2Vec: {word} に類似する単語 ===")
print(word2vec_model.wv.most_similar(word))

# FastText の類似語を表示
print(f"\n=== FastText: {word} に類似する単語 ===")
print(fasttext_model.wv.most_similar(word))
```

### **解説**
- **Word2Vec**：単語間の意味的な類似性を捉え、ベクトル表現に変換。
- **FastText**：単語内部の文字情報（サブワード）を考慮し、未知の単語にも対応。

---

## **3. BERTによるベクトル化**
BERTは文の意味を深く捉えることができるモデルで、文章全体のコンテキストを考慮しながらベクトル化を行います。

### **Pythonコード**
```python
import torch
from transformers import BertModel, BertTokenizer

# 事前学習済みのBERTモデル（日本語）
MODEL_NAME = "cl-tohoku/bert-base-japanese"
tokenizer = BertTokenizer.from_pretrained(MODEL_NAME)
model = BertModel.from_pretrained(MODEL_NAME)

# 対象の文章
documents = [
    "オドアケルが西ローマ帝国を滅ぼす",
    "西ローマ帝国は476年に滅亡した",
    "オドアケルは西ローマ帝国最後の皇帝を退位させた",
    "476年にロムルス・アウグストゥルスが退位"
]

# 各文章のベクトルを取得
def get_bert_vector(text):
    inputs = tokenizer(text, return_tensors="pt", padding=True, truncation=True, max_length=50)
    with torch.no_grad():
        outputs = model(**inputs)
    return outputs.last_hidden_state[:, 0, :].squeeze().numpy()  # [CLS]トークンのベクトルを取得

# 文ごとのBERTベクトルを取得
bert_vectors = {doc: get_bert_vector(doc) for doc in documents}

# ベクトルを表示
print("=== BERT ベクトル ===")
for doc, vec in bert_vectors.items():
    print(f"\n文章: {doc}")
    print(vec)
```

### **解説**
- BERTの `[CLS]` トークンの出力を使用し、文章全体のベクトルを取得。
- 単語レベルではなく、**文脈を考慮した意味のベクトル** になる。

---

## **まとめ**
| 手法 | 特徴 |
|------|------|
| **TF-IDF, BoW** | 単語の頻度を考慮し、シンプルなベクトル化 |
| **Word2Vec** | 単語間の意味的な関係をベクトル化 |
| **FastText** | サブワードを考慮し、未知語にも対応 |
| **BERT** | 文脈を考慮した高度な意味ベクトルを生成 |