Skip to content

12. 自然言語処理 ③:テキストのベクトル化と分類

第 12 回では、単語やテキストの意味を捉えるベクトル化手法について学びます。第 11 回で学んだ BoW / TF-IDF の限界を理解し、より高度な手法である Word2Vec や Sentence Transformers を紹介します。

12.1 BoW / TF-IDF の限界

12.1.1 単語の意味を考慮できない

第 11 回で学んだ Bag-of-Words や TF-IDF は、シンプルで実用的な手法ですが、いくつかの限界があります。

例 1: 類似した意味の単語

文 A: 「犬が走っている」
文 B: 「猫が走っている」
文 C: 「車が走っている」

BoW / TF-IDF では、「犬」「猫」「車」は全く別の単語として扱われます。しかし、意味的には「犬」と「猫」は「動物」として近い関係にあります。

例 2: 同義語・類義語

文 A: 「この映画は面白い」
文 B: 「この映画は楽しい」

「面白い」と「楽しい」は似た意味ですが、BoW / TF-IDF では全く異なる単語として扱われ、類似度が低くなってしまいます。

12.1.2 文脈を考慮できない

第 10 回で触れた例を思い出してみましょう。

文: 「黒い目の大きな猫」

この文で「大きい」のは「目」でしょうか、「猫」でしょうか?BoW / TF-IDF では、このような文脈による意味の違いを区別できません。

12.1.3 スパース(疎)なベクトル

BoW / TF-IDF では、語彙数が増えるとベクトルの次元数も増加します。しかし、各文書には語彙の一部しか出現しないため、ほとんどの要素が 0 になります(スパースなベクトル)。

# 例:語彙数が 10,000 の場合
# 文章「私は猫が好きです」のベクトル
# → [0, 0, 0, ..., 1, ..., 0, 1, ..., 0]  # ほとんどが 0

これらの問題を解決するために、単語の意味を考慮したベクトル化手法 が開発されました。

12.2 Embedding(埋め込み)とは

12.2.1 Embedding の概念

Embedding(埋め込み) とは、単語やテキストを固定長の密なベクトルに変換する手法です。「埋め込み」という名前は、高次元の離散的なデータ(単語)を、低次元の連続的なベクトル空間に「埋め込む」ことに由来します。

BoW / TF-IDF との違い:

特徴 BoW / TF-IDF Embedding
ベクトルの種類 スパース(疎) 密(Dense)
次元数 語彙数に依存(数千〜数万) 固定(数百程度)
意味の表現 できない できる
類義語の扱い 別々のベクトル 近いベクトル

12.2.2 なぜ Embedding が有効か

Embedding では、意味的に近い単語やテキストが、ベクトル空間上でも近くに配置されます。

たとえば、Multimodal Embedding Models - Weaviate の Figure 1 のように、「犬」と「猫」は近く、「バナナ」と「リンゴ」も近い位置に配置されます。これにより、単語の意味的な関係を数値で扱えるようになります。

12.3 Word2Vec

12.3.1 Word2Vec とは

Word2Vec は、単語の Embedding を学習する手法です。2013 年に Google の研究者によって提案されました。

特徴:

  • 似た文脈で使われる単語は、似たベクトルになる
  • 固定長の密なベクトル(例:300 次元)で表現
  • 単語の意味の演算ができる

有名な例:

\[ \text{king} - \text{man} + \text{woman} \approx \text{queen} \]

「王」から「男性」の意味を引き、「女性」の意味を足すと、「女王」に近いベクトルになります。

12.3.2 Word2Vec の仕組み(概要)

Word2Vec は、大量のテキストデータから「単語の周辺にどんな単語が出現するか」を学習します。

「私 は 猫 が 好き です」
「猫」の周辺には「私」「は」「が」「好き」が出現

同じような文脈で使われる単語(例:「犬」と「猫」)は、似たベクトルになります。これは 「分布仮説」(似た文脈に出現する単語は似た意味を持つ)に基づいています。

12.3.3 Word2Vec の限界

Word2Vec にも限界があります。

  • 単語単位: テキスト全体の意味を直接表現できない
  • 文脈を考慮しない: 同じ単語は常に同じベクトル(多義語の区別ができない)
  • 未知語に対応できない: 学習データにない単語はベクトル化できない

12.4 Transformer と BERT

12.4.1 Transformer とは

Transformer は、2017 年に Google が発表した深層学習モデルのアーキテクチャです。現在の自然言語処理の基盤技術となっています。

Transformer の特徴:

  • Attention(注意機構): 文中の重要な部分に「注意」を向けて処理
  • 並列処理: 文全体を一度に処理できるため高速
  • 長距離依存: 文の離れた位置にある単語同士の関係も捉えられる
「私 は 昨日 買った 本 を 読んでいる」
     ↓ Attention
「読んでいる」は「本」に注意を向ける
「買った」も「本」に注意を向ける

12.4.2 BERT とは

BERT(Bidirectional Encoder Representations from Transformers) は、2018 年に Google が発表した言語モデルです。Transformer をベースに、大量のテキストデータで事前学習されています。

BERT の特徴:

  • 双方向: 文の前後両方の文脈を考慮
  • 文脈依存: 同じ単語でも文脈によって異なるベクトルになる
  • 事前学習: 大量のデータで学習済みなので、少ないデータでも高精度

Word2Vec との違い:

特徴 Word2Vec BERT
単位 単語 単語・文
文脈 考慮しない 考慮する
多義語 区別できない 区別できる
モデルサイズ 小さい 大きい

12.4.3 事前学習と転移学習

BERT などのモデルは、以下の 2 段階で利用されます。

  1. 事前学習(Pre-training): 大量のテキストデータで言語の一般的な知識を学習
  2. ファインチューニング(Fine-tuning): 特定のタスク(感情分析など)用に追加学習

私たちは、すでに事前学習されたモデルを使うことで、少ないデータでも高精度な分類が可能になります。これを 転移学習 と呼びます。

12.5 Sentence Transformers

12.5.1 Sentence Transformers とは

Sentence Transformers は、文全体を一つのベクトル(Embedding)に変換するためのライブラリです。BERT などの Transformer モデルをベースに、文の意味を捉えたベクトル(文書埋め込み / Sentence Embedding)を生成します。

特徴:

  • 文書全体の意味をベクトル化
  • 文脈を考慮した表現
  • 多言語対応のモデルも利用可能
  • 事前学習済みモデルを簡単に利用できる

12.5.2 インストール

Google Colaboratory やローカル環境で Sentence Transformers がインストールされていない場合は、以下のコマンドでインストールします。CHIKUWA Editor にはインストール済みです。

!pip install sentence-transformers

12.5.3 基本的な使い方

Sentence Transformers の基本的な使い方を見てみましょう。

事前学習済みモデルを読み込むには、SentenceTransformer クラスを使用します。モデル名を指定してインスタンスを作成します。

文をベクトルに変換するには、encode メソッドを使用します。文(または文のリスト)を受け取り、ベクトル(NumPy 配列)を返します。

from sentence_transformers import SentenceTransformer

# モデルの読み込み(多言語対応モデル)
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')

# 文のリスト
sentences = [
    "私は機械学習が好きです",
    "私は深層学習が好きです",
    "今日は天気が良いです"
]

# 文をベクトルに変換
embeddings = model.encode(sentences)

print(f"ベクトルの形状: {embeddings.shape}")
print(f"1文目のベクトル(最初の10要素): {embeddings[0][:10]}")
Output
ベクトルの形状: (3, 384)
1文目のベクトル(最初の10要素): [ 0.04924066 -0.22802348 -0.06099672 -0.26507816 -0.13282439 -0.01166196
 -0.02531664  0.07985897  0.03808774  0.22141635]

各文が 384 次元の密なベクトルに変換されました。

12.5.4 使用するモデルについて

本講義では、paraphrase-multilingual-MiniLM-L12-v2 というモデルを使用します。

項目 内容
モデル名 paraphrase-multilingual-MiniLM-L12-v2
対応言語 50 以上の言語(日本語を含む)
ベクトル次元 384 次元
特徴 軽量で高速、類似文書検索に適している

このモデルは、Hugging Face で公開されています。

他のモデル

Sentence Transformers では、その他にもさまざまな事前学習済みモデルを利用できます。

モデル 言語 次元 特徴
all-MiniLM-L6-v2 英語 384 軽量・高速
all-mpnet-base-v2 英語 768 高精度
paraphrase-multilingual-MiniLM-L12-v2 多言語 384 日本語対応
paraphrase-multilingual-mpnet-base-v2 多言語 768 日本語対応・高精度

モデル一覧: Sentence Transformers Pretrained Models

12.6 コサイン類似度による類似文書検索

12.6.1 コサイン類似度とは

コサイン類似度(Cosine Similarity) は、2 つのベクトルがなす角度のコサイン値を使って類似度を測る方法です。

\[ \text{cosine similarity}(\mathbf{A}, \mathbf{B}) = \frac{\mathbf{A} \cdot \mathbf{B}}{|\mathbf{A}| \times |\mathbf{B}|} \]

コサイン類似度の特徴:

  • 値の範囲: -1 から 1
  • 1 に近い: 非常に似ている
  • 0 に近い: 似ていない
  • -1 に近い: 正反対の意味

12.6.2 類似度の計算

Sentence Transformers で生成したベクトルを使って、文間の類似度を計算してみましょう。

コサイン類似度を計算するには、scikit-learn の cosine_similarity 関数を使用します。ベクトルの配列を受け取り、全ペアの類似度を含む行列を返します。

from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity

# モデルの読み込み
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')

# 文のリスト
sentences = [
    "私は機械学習が好きです",
    "私は深層学習が好きです",
    "今日は天気が良いです",
    "機械学習と深層学習を勉強しています"
]

# ベクトル化
embeddings = model.encode(sentences)

# コサイン類似度を計算
similarity_matrix = cosine_similarity(embeddings)

print("類似度行列:")
for i, sent in enumerate(sentences):
    print(f"\n{i}: {sent}")
    for j, sim in enumerate(similarity_matrix[i]):
        print(f"  vs 文{j}: {sim:.3f}")
Output
類似度行列:

文0: 私は機械学習が好きです
  vs 文0: 1.000
  vs 文1: 0.750
  vs 文2: 0.164
  vs 文3: 0.713

文1: 私は深層学習が好きです
  vs 文0: 0.750
  vs 文1: 1.000
  vs 文2: 0.143
  vs 文3: 0.717

文2: 今日は天気が良いです
  vs 文0: 0.164
  vs 文1: 0.143
  vs 文2: 1.000
  vs 文3: -0.041

文3: 機械学習と深層学習を勉強しています
  vs 文0: 0.713
  vs 文1: 0.717
  vs 文2: -0.041
  vs 文3: 1.000

12.7 Sentence Transformers による文書分類

12.7.1 分類の流れ

Sentence Transformers を使った文書分類は、以下の流れで行います。

  1. 文を Sentence Transformers でベクトル化
  2. ベクトルを特徴量として分類器(ロジスティック回帰など)に入力
  3. 分類モデルを学習・予測

12.7.2 感情分析の実装

映画レビューの感情分析を Sentence Transformers で実装してみましょう。

import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

# データの読み込み
df = pd.read_csv('movie_reviews.csv')

print(f"データ数: {len(df)}")
print(df['label'].value_counts())

# モデルの読み込み
model = SentenceTransformer('sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2')

# 文をベクトル化(少し時間がかかります)
print("\nベクトル化中...")
embeddings = model.encode(df['text'].tolist())

print(f"ベクトルの形状: {embeddings.shape}")

# ラベルを数値に変換
df['label_num'] = (df['label'] == 'positive').astype(int)

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(
    embeddings, df['label_num'],
    test_size=0.2,
    random_state=42
)

# ロジスティック回帰で学習
clf = LogisticRegression(random_state=42, max_iter=1000)
clf.fit(X_train, y_train)

# 予測
y_pred = clf.predict(X_test)

# 評価
accuracy = accuracy_score(y_test, y_pred)
print(f"\n精度: {accuracy:.2%}")

print("\n分類レポート:")
print(classification_report(y_test, y_pred, target_names=['Negative', 'Positive']))
Output
データ数: 200
label
positive    100
negative    100
Name: count, dtype: int64

ベクトル化中...
ベクトルの形状: (200, 384)

精度: 90.00%

分類レポート:
              precision    recall  f1-score   support

    Negative       0.86      0.95      0.90        19
    Positive       0.95      0.86      0.90        21

    accuracy                           0.90        40
   macro avg       0.90      0.90      0.90        40
weighted avg       0.90      0.90      0.90        40

線形分類器を使う場合のヒント

ロジスティック回帰や SVM などの線形分類器を使う場合は、encode メソッドに normalize_embeddings=True を指定してベクトルを正規化すると、精度が向上することがあります。

embeddings = model.encode(sentences, normalize_embeddings=True)

正規化により、すべてのベクトルの長さが 1 に揃えられ、方向(意味の類似性)のみで比較されるようになります。

12.8 演習問題

演習 12-1: 感情分析の精度比較

演習 12-1

movie_reviews.csv を使って、TF-IDF と Sentence Transformers の感情分析の精度を比較してください。

タスク:

  1. TF-IDF でベクトル化し、ロジスティック回帰で分類
  2. Sentence Transformers でベクトル化し、ロジスティック回帰で分類
  3. 両者の精度を比較

12.9 まとめ

本章では、単語・テキストの意味を捉えるベクトル化手法について学びました。

第 12 回のまとめ

BoW / TF-IDF の限界

  • 単語の意味を考慮できない
  • 文脈を考慮できない
  • スパースなベクトル

Embedding(埋め込み)

  • 単語やテキストを固定長の密なベクトルに変換
  • 意味的に近いものは、ベクトル空間上でも近くに配置

Word2Vec

  • 単語の意味をベクトル化
  • 似た文脈の単語 → 似たベクトル
  • 単語の演算が可能(king - man + woman ≈ queen)

Transformer / BERT

  • Attention 機構により文脈を考慮
  • 事前学習 + ファインチューニングで高精度

Sentence Transformers

  • 文全体を一つのベクトルに変換
  • 文脈を考慮した表現
  • 事前学習済みモデルを簡単に利用可能
  • paraphrase-multilingual-MiniLM-L12-v2: 日本語対応の軽量モデル

コサイン類似度

  • ベクトル間の角度で類似度を測る
  • 1 に近いほど類似
自然言語処理(第 10 〜 12 回)の総まとめ

第 10 回:テキストの前処理

  • テキストクリーニング(URL、記号の削除)
  • 形態素解析(MeCab)
  • 正規化(ストップワード除去、品詞フィルタリング)

第 11 回:ベクトル化と文書分類

  • Bag-of-Words(単語の出現回数)
  • TF-IDF(単語の重要度を考慮)
  • ロジスティック回帰による分類

第 12 回:意味を捉えるベクトル化

  • Embedding(埋め込み)の概念
  • Word2Vec(単語の意味をベクトル化)
  • Transformer / BERT(文脈を考慮)
  • Sentence Transformers(文全体をベクトル化)