AIの要素技術について記述します。word2vec は、単語を意味や文脈の特徴を反映した数値のベクトルに変換します。
word2vec
データセット(コーパス)と、CBOW または Skip-gram のアルゴリズムを使用して、モデルを作成する
モデルを使用して、入力した単語に意味が近い単語を検索できる
モデルを使用して、単語の引き算ができる(「王様」-「男」+「女」=「女王」)
- CBOW(Continuous Bag-of-Words)
周囲の単語から対象の単語を予測
- スキップグラム
対象の単語から周囲の単語を予測
サンプルプログラム
analogies_text8.py
処理内容(skip-gram)
語彙 = ["the", "of", "and", "to", "a", ..., "king", ..., "man", ..., "woman", ..., "queen", ...]
入力した単語をワンホット表現する。各単語は長さ V のベクトルに変換される
入力埋め込み行列 (V × d) との掛け算で低次元ベクトルに変換する
出力埋め込み行列でスコア化(logits)
ソフトマックス関数で、出力確率を正規化
学習は、誤差逆伝播を使用して、入力埋め込み行列と出力埋め込み行列を更新
pip install gensim
import gensim
import gensim.downloader as api
from gensim.models import Word2Vec
import numpy as np
import random
# 再現性のためのシード
SEED = 42
np.random.seed(SEED)
random.seed(SEED)
def main():
# text8 の全文を一度リスト化(1700万語ほど)
print("text8 をダウンロード中...")
raw = list(api.load("text8"))
if len(raw) == 0:
raise ValueError("text8 の読み込みに失敗しました。")
if isinstance(raw[0], str):
# ただの単語列 → 200語ごとに擬似文に分割
sentences = [raw[i:i+200] for i in range(0, len(raw), 200)]
elif isinstance(raw[0], list) and (len(raw[0]) > 0 and isinstance(raw[0][0], str)):
# すでに文ごとの list[list[str]]
sentences = raw
else:
raise TypeError("想定外のデータ構造です。先頭要素の型を確認してください。")
# Word2Vec モデルの学習
print("Word2Vec を学習中...")
model = Word2Vec(
sentences=sentences,
vector_size=200,
window=5,
min_count=5,
sg=1, # skip-gram
negative=10,
epochs=5,
workers=4,
seed=SEED
)
kv = model.wv
# 語彙確認
words = ["king", "man", "woman", "queen"]
missing = [w for w in words if w not in kv.key_to_index]
if missing:
print("語彙に見つからなかった単語:", missing)
print("min_count を下げる / epochs を増やす / vector_size を上げる などを試してください。")
return
# アナロジー: king - man + woman ≈ ?
result = kv.most_similar(positive=["king", "woman"], negative=["man"], topn=10)
print("\nAnalogy: king - man + woman ≈ ?")
for rank, (word, score) in enumerate(result, 1):
print(f"{rank:2d}. {word:>10s} (cos={score:.4f})")
# queen とのコサイン類似度
target_vec = kv["king"] - kv["man"] + kv["woman"]
cos_sim_queen = np.dot(target_vec, kv["queen"]) / (
np.linalg.norm(target_vec) * np.linalg.norm(kv["queen"])
)
print(f"\ncosine(king - man + woman, queen) = {cos_sim_queen:.4f}")
if __name__ == "__main__":
main()
text8 をダウンロード中...
Word2Vec を学習中...
Analogy: king - man + woman ≈ ?
1. queen (cos=0.6207)
2. daughter (cos=0.5205)
3. isabella (cos=0.5111)
4. consort (cos=0.5101)
5. matilda (cos=0.4994)
6. montferrat (cos=0.4934)
7. infanta (cos=0.4928)
8. anjou (cos=0.4897)
9. dowager (cos=0.4889)
10. melisende (cos=0.4871)
cosine(king - man + woman, queen) = 0.6515
画像や音声の場合
画像:VGG、ResNet
音声:LSTM、GRU
文書や段落の場合(doc2vec)
doc2vec は、 word2vec の拡張版で、「文書や段落をベクトルに変換する」ための手法
他には、「系列を系列に変換」する BERT や text-embedding-3 がある
系列モデル
RNN
時系列データを扱う
逐次処理型
LSTM
RNN の、過去に遡るにつれて情報が消えていってしまう問題に対応
「大事なことをメモ帳に残す」仕組みを持っていて、長い間でも覚えていられる
時系列データを扱うデファクトスタンダード
逐次処理型
トランスフォーマー
2017年に登場したモデル("Attention is All You Need" 論文)
Source-Target Attention、Self-Attention(Multi-Head Attention)
クエリ、キー、バリュー
BERT や text-embedding-3 の基盤
「全単語を並列に処理」できる