STEP 6:GloVeとfastText

🌐 STEP 6: GloVeとfastText

Word2Vecの改良版であるGloVeと、サブワード情報を活用するfastTextを学びます

📋 このステップで学ぶこと

  • GloVe(Global Vectors)の仕組みと共起行列
  • Word2VecとGloVeの違い
  • fastTextの特徴(サブワード情報の活用)
  • 未知語(OOV)への対応
  • 事前学習済みGloVeとfastTextの利用
  • 3つの手法の比較と使い分け

練習問題: 4問

💻 実行環境について

このステップのコードはGoogle Colabで実行できます。
Gensimを使って事前学習済みモデルをダウンロードします。
初回ダウンロードには時間がかかる場合があります。

🌍 1. GloVe(Global Vectors)の概要

GloVeは、2014年にスタンフォード大学が発表した単語埋め込み手法です。 Word2Vecとは異なるアプローチで単語の意味を学習します。

1-1. Word2Vecの復習と限界

まず、STEP 5で学んだWord2Vecの特徴を振り返りましょう。

【Word2Vecの特徴(復習)】 ■ 学習方法:予測ベース(Prediction-based) 文章を1つのウィンドウずつ処理して、 「周辺の単語から中心を予測」または 「中心の単語から周辺を予測」 例:ウィンドウサイズ=2 “I love natural language processing” ↓ [I, love] → natural ← [language, processing] (周辺) (予測) (周辺) ■ 問題点 ・各ウィンドウを独立に処理 ・コーパス全体の統計情報を直接使わない ・同じ単語ペアが何度も出現しても、毎回独立に計算

1-2. GloVeの基本アイデア

💡 GloVeの発想

「コーパス全体の共起情報を先に集計してから学習しよう!」

GloVeは「Global Vectors」の略で、 グローバル(全体)な統計情報を活用します。

【Word2Vec vs GloVe の違い】 ■ Word2Vec(局所的) 文章: “I love cats” “I love dogs” “cats are cute” 処理方法: 1. “I love cats” のウィンドウを処理 2. “I love dogs” のウィンドウを処理 3. “cats are cute” のウィンドウを処理 … → 各ウィンドウを独立に処理 ■ GloVe(グローバル) 文章: “I love cats” “I love dogs” “cats are cute” 処理方法: 1. まず全文章をスキャンして共起をカウント – “I”と”love”が一緒に出現: 2回 – “love”と”cats”が一緒に出現: 1回 – “love”と”dogs”が一緒に出現: 1回 … 2. 共起行列を作成 3. 共起行列から単語ベクトルを学習 → 全体の統計を先に計算

1-3. 共起行列(Co-occurrence Matrix)とは?

共起行列は、単語ペアが「一緒に出現する回数」をまとめた表です。 これがGloVeの核心部分です。

【共起行列の作り方】 ■ 元の文章 文1: “I love cats” 文2: “I love dogs” 文3: “cats are cute” 文4: “dogs are cute” ■ ウィンドウサイズ = 1(前後1単語を見る) 各単語の周辺をカウント: – “I”の周辺: “love”×2 – “love”の周辺: “I”×2, “cats”×1, “dogs”×1 – “cats”の周辺: “love”×1, “are”×1 – “dogs”の周辺: “love”×1, “are”×1 – “are”の周辺: “cats”×1, “dogs”×1, “cute”×2 – “cute”の周辺: “are”×2 ■ 共起行列(一部) I love cats dogs are cute I 0 2 0 0 0 0 love 2 0 1 1 0 0 cats 0 1 0 0 1 0 dogs 0 1 0 0 1 0 are 0 0 1 1 0 2 cute 0 0 0 0 2 0
💡 共起行列から分かること
  • “I”と”love”は2回一緒に出現 → 関連が強い
  • “cats”と”dogs”は直接共起しないが、”love”や”are”と同じ共起パターン → 似た単語
  • 共起パターンが似ている単語は、似た意味を持つ可能性が高い

1-4. GloVeの学習目標

GloVeは、共起行列の情報を低次元のベクトルで表現することを目指します。

【GloVeの学習目標】 単語iと単語jのベクトルの内積が、 共起回数の対数に近くなるようにする 数式: w_i · w_j + b_i + b_j ≈ log(X_ij) w_i: 単語iのベクトル w_j: 単語jのベクトル b_i, b_j: バイアス項 X_ij: 単語iとjの共起回数 【例】 “love”と”cats”の共起回数 = 1 → log(1) = 0 → w_love · w_cats + b_love + b_cats ≈ 0 “I”と”love”の共起回数 = 2 → log(2) ≈ 0.69 → w_I · w_love + b_I + b_love ≈ 0.69 共起が多い → 内積が大きい → 似たベクトルに

1-5. GloVeの損失関数

【GloVeの損失関数】 J = Σ f(X_ij) × (w_i · w_j + b_i + b_j – log(X_ij))² ■ 各部分の意味 (w_i · w_j + b_i + b_j – log(X_ij))² → 予測値と実際の共起の差(二乗誤差) f(X_ij) → 重み関数(共起回数に応じた重み) ■ 重み関数 f(X_ij) の役割 問題: “the”, “a”などの頻出語は共起回数が非常に多い → これらに引っ張られてしまう 解決策: f(X_ij)で重みを調整 ・共起が少ない → 重み小さい(ノイズかも) ・共起が多すぎる → 重み抑制(頻出語の影響を減らす) ・適度な共起 → 重み大きい

📊 2. Word2Vec vs GloVe の比較

2-1. アプローチの違い

【2つのアプローチ】 ■ Word2Vec: 予測ベース(Prediction-based) ・ニューラルネットワークで単語を予測 ・局所的なウィンドウを処理 ・各ウィンドウで勾配更新 例えるなら: 「1問ずつ問題を解いて、その場で答え合わせ」 ■ GloVe: カウントベース(Count-based) ・共起行列を事前に計算 ・全体の統計情報を活用 ・行列分解に近い手法 例えるなら: 「まず全体を俯瞰してから、パターンを見つける」

2-2. 比較表

項目 Word2Vec GloVe
学習方法 予測ベース(局所的) カウントベース(グローバル)
情報の使い方 各ウィンドウを独立処理 全体の共起統計を利用
学習速度 普通 速い(共起行列を事前計算)
メモリ 少ない 多い(共起行列が必要)
精度 高い 同等〜やや高い
理論的明確さ やや不明確 明確(目的関数が明示的)
💡 どちらが優れている?

結論:どちらも同程度の性能です。 タスクやデータによって若干の差が出ますが、 実用上はどちらを使っても問題ありません。 GloVeの方が理論的に明確なので、研究では好まれることがあります。

💻 3. GloVeの実装

GloVeの事前学習済みモデルをGensimで使ってみましょう。

3-1. 事前学習済みGloVeのダウンロード

# Gensimのダウンローダーをインポート import gensim.downloader as api # 利用可能なGloVeモデルを確認 print(“利用可能なGloVeモデル:”) for name in api.info()[‘models’].keys(): if ‘glove’ in name: print(f” – {name}”)
実行結果: 利用可能なGloVeモデル: – glove-wiki-gigaword-50 – glove-wiki-gigaword-100 – glove-wiki-gigaword-200 – glove-wiki-gigaword-300 – glove-twitter-25 – glove-twitter-50 – glove-twitter-100 – glove-twitter-200

3-2. GloVeモデルの読み込み

# GloVe 100次元モデルをダウンロード(約128MB) # ※ 初回は数分かかります import gensim.downloader as api print(“モデルをダウンロード中…”) glove = api.load(“glove-wiki-gigaword-100”) print(“完了!”) # モデルの情報を確認 print(f”\n語彙数: {len(glove)}”) print(f”ベクトル次元数: {glove.vector_size}”)
実行結果: モデルをダウンロード中… [==================================================] 100% 完了! 語彙数: 400000 ベクトル次元数: 100

3-3. 類似単語の検索

# “computer”に似た単語を検索 similar = glove.most_similar(“computer”, topn=5) print(“‘computer’に似た単語:”) for word, similarity in similar: print(f” {word}: {similarity:.4f}”)
実行結果: ‘computer’に似た単語: computers: 0.8789 software: 0.8124 technology: 0.7823 electronic: 0.7645 digital: 0.7534

3-4. 単語演算(アナロジー)

# 有名な単語演算: king – man + woman = ? result = glove.most_similar( positive=[“king”, “woman”], # 足す negative=[“man”], # 引く topn=3 ) print(“king – man + woman = ?”) for word, sim in result: print(f” {word}: {sim:.4f}”)
実行結果: king – man + woman = ? queen: 0.8523 princess: 0.6978 throne: 0.6534
# 都市と国の関係: tokyo – japan + france = ? result = glove.most_similar( positive=[“tokyo”, “france”], negative=[“japan”], topn=3 ) print(“tokyo – japan + france = ?”) for word, sim in result: print(f” {word}: {sim:.4f}”)
実行結果: tokyo – japan + france = ? paris: 0.7856 french: 0.6234 lyon: 0.5987
✨ Word2VecとGloVeの結果は似ている

どちらも「king – man + woman = queen」や 「tokyo – japan + france = paris」のような アナロジータスクで高精度な結果を返します。

🚀 4. fastText:未知語への対応

fastTextは、2016年にFacebook(現Meta)が発表した手法です。 Word2VecとGloVeの大きな問題を解決します。

4-1. Word2Vec/GloVeの問題:未知語(OOV)

⚠️ 未知語問題(Out-Of-Vocabulary Problem)

Word2VecとGloVeは、訓練データにない単語を処理できません。

【未知語問題の具体例】 ■ 訓練データに含まれる単語 “play”, “playing”, “played”, “player” ■ テスト時に遭遇した単語 “replaying” ← 訓練データにない! ■ Word2Vec/GloVeの挙動 model.wv[“replaying”] → KeyError: “replaying”が見つかりません ❌ ■ 問題が起きやすいケース ・新語・造語: “ChatGPT”, “metaverse” ・専門用語: “immunotherapy”, “cryptocurrency” ・スペルミス: “computr”, “langauge” ・活用形: “unhappiness”, “uncomputerized”

4-2. fastTextの解決策:サブワード

💡 fastTextの革新的アイデア

「単語を文字の並び(サブワード)に分解して学習する」

単語全体だけでなく、その部分(文字n-gram)も一緒に学習します。 これにより、未知語でもベクトルを生成できます。

4-3. サブワード(文字n-gram)とは?

【サブワードの作り方】 単語: “playing” ■ ステップ1: 境界記号を追加 “” (<と>は単語の開始と終了を示す特殊記号) ■ ステップ2: 文字n-gramに分解(n=3の場合) 連続する3文字を全て抽出: ← 最後の3文字 ■ 結果 “playing”のサブワード(3-gram): [““] ■ fastTextでの単語ベクトル “playing”のベクトル = “playing”自体のベクトル + 全サブワードベクトルの合計

4-4. なぜサブワードで未知語に対応できる?

【サブワードによる未知語対応】 ■ 訓練時に学習した単語 “play” → サブワード: [““] “playing” → サブワード: [““] ■ 未知語に遭遇 “replaying” → サブワード: [““] ■ 注目ポイント “replaying”のサブワードの多くは既に学習済み! – “pla” → “play”, “playing”で学習済み ✓ – “lay” → “play”, “playing”で学習済み ✓ – “ayi” → “playing”で学習済み ✓ – “yin” → “playing”で学習済み ✓ – “ing” → “playing”で学習済み ✓ ■ 結果 “replaying”のベクトル = 学習済みサブワードの合計 → “playing”に近いベクトルが生成される! ✓
✨ fastTextの強み
  • 未知語対応:訓練データにない単語もベクトル化可能
  • 形態的類似性:“play”と”playing”が近いベクトルに
  • スペルミスに強い:“computer”と”compuuter”も近い
  • 希少語に強い:出現回数が少なくてもサブワードで補完

4-5. スペルミスへの対応

【スペルミスでも類似ベクトル】 正しいスペル: “computer” サブワード: [““] スペルミス: “compuuter”(uが1つ多い) サブワード: [““] 共通するサブワード: “” → 7個中7個が共通! 結果: コサイン類似度 ≈ 0.85(非常に高い) → スペルミスでも似た単語として認識 ✓

💻 5. fastTextの実装

5-1. 自分のデータでfastTextを学習

ステップ1:必要なライブラリのインポート

# FastTextをGensimからインポート from gensim.models import FastText print(“FastTextのインポート完了!”)

ステップ2:学習データの準備

# サンプルデータ(単語のリストのリスト) sentences = [ [“I”, “love”, “natural”, “language”, “processing”], [“I”, “love”, “machine”, “learning”], [“natural”, “language”, “processing”, “is”, “amazing”], [“machine”, “learning”, “is”, “powerful”], [“deep”, “learning”, “uses”, “neural”, “networks”], [“neural”, “networks”, “are”, “powerful”], [“I”, “study”, “deep”, “learning”, “every”, “day”], [“NLP”, “uses”, “machine”, “learning”, “techniques”] ] print(f”学習データ: {len(sentences)}文”)
実行結果: 学習データ: 8文

ステップ3:FastTextモデルの学習

# FastTextモデルの訓練 model = FastText( sentences=sentences, # 学習データ vector_size=100, # ベクトルの次元数 window=5, # ウィンドウサイズ min_count=1, # 最低出現回数 workers=4, # 並列処理数 sg=1, # 0=CBOW, 1=Skip-gram min_n=3, # 最小文字n-gram(3文字から) max_n=6, # 最大文字n-gram(6文字まで) epochs=100 # 学習回数 ) print(“モデルの学習完了!”)
実行結果: モデルの学習完了!
💡 パラメータの解説
  • min_n=3: 最小3文字のサブワードを使用
  • max_n=6: 最大6文字のサブワードを使用
  • 例: “playing”から3〜6文字のサブワードを抽出
  • 日本語の場合はmin_n=2程度がおすすめ

5-2. 既知語と未知語のベクトル取得

# 既知語(訓練データに含まれる) print(“【既知語のベクトル】”) print(f”‘learning’のベクトル(最初の5次元):”) print(model.wv[“learning”][:5]) # 未知語(訓練データに含まれない)でも取得可能! print(“\n【未知語のベクトル】”) print(f”‘learnings’のベクトル(最初の5次元):”) print(model.wv[“learnings”][:5]) print(f”\n’deeplearning’のベクトル(最初の5次元):”) print(model.wv[“deeplearning”][:5])
実行結果: 【既知語のベクトル】 ‘learning’のベクトル(最初の5次元): [-0.0234 0.0156 -0.0478 0.0123 0.0345] 【未知語のベクトル】 ‘learnings’のベクトル(最初の5次元): [-0.0198 0.0142 -0.0423 0.0115 0.0312] ‘deeplearning’のベクトル(最初の5次元): [-0.0215 0.0148 -0.0445 0.0119 0.0328]
🎉 未知語でもベクトルが生成された!

Word2VecやGloVeでは”learnings”や”deeplearning”は エラーになりますが、fastTextではサブワードから ベクトルを生成できます。

5-3. 事前学習済みfastTextの利用

# 事前学習済みfastTextをダウンロード import gensim.downloader as api print(“モデルをダウンロード中…”) fasttext = api.load(“fasttext-wiki-news-subwords-300”) print(“完了!”) # 類似単語の検索 print(“\n’computer’に似た単語:”) for word, sim in fasttext.most_similar(“computer”, topn=5): print(f” {word}: {sim:.4f}”)
実行結果: モデルをダウンロード中… [==================================================] 100% 完了! ‘computer’に似た単語: computers: 0.8234 laptop: 0.7856 computing: 0.7623 PC: 0.7456 software: 0.7234

5-4. 完成コード

※コードが長いため、横スクロールできます。

# fastText完成コード from gensim.models import FastText # ========== 1. データの準備 ========== sentences = [ [“I”, “love”, “natural”, “language”, “processing”], [“I”, “love”, “machine”, “learning”], [“natural”, “language”, “processing”, “is”, “amazing”], [“machine”, “learning”, “is”, “powerful”], [“deep”, “learning”, “uses”, “neural”, “networks”] ] # ========== 2. モデルの学習 ========== model = FastText( sentences=sentences, vector_size=100, window=5, min_count=1, sg=1, min_n=3, max_n=6, epochs=100 ) # ========== 3. 既知語のテスト ========== print(“【既知語】”) print(f”‘learning’: {model.wv[‘learning’][:3]}”) # ========== 4. 未知語のテスト(fastTextの強み)========== print(“\n【未知語】”) print(f”‘learnings’: {model.wv[‘learnings’][:3]}”) print(f”‘unlearning’: {model.wv[‘unlearning’][:3]}”) # ========== 5. モデルの保存 ========== model.save(“fasttext_model.bin”) print(“\nモデルを保存しました”)

📊 6. 3つの手法の比較と使い分け

6-1. Word2Vec vs GloVe vs fastText

項目 Word2Vec GloVe fastText
発表年 2013年 Google 2014年 Stanford 2016年 Facebook
学習方法 予測(局所的) カウント(グローバル) 予測+サブワード
未知語対応 ❌ 不可 ❌ 不可 ✅ 可能
スペルミス ❌ 弱い ❌ 弱い ✅ 強い
学習速度 普通 速い やや遅い
メモリ 少ない 多い 多い

6-2. どの手法を選ぶべき?

💡 使い分けガイド

🎯 Word2Vecを選ぶ場合:

  • 標準的なタスク、クリーンなデータ
  • 未知語が少ない場合
  • メモリが限られている場合

🌍 GloVeを選ぶ場合:

  • グローバルな統計情報を重視
  • 学習を高速化したい
  • 理論的に明確な手法を使いたい

🚀 fastTextを選ぶ場合(推奨):

  • 未知語が多い(SNS、専門用語)
  • スペルミスが多いデータ
  • 希少語・新語を扱う
  • → 実務では最も汎用的!

6-3. 実務での推奨

🏆 結論:迷ったらfastText

実務ではfastTextが最も汎用的です。

  • 未知語に強い → SNSテキストでも対応可能
  • スペルミスに強い → ユーザー入力データで有利
  • 精度も同等 → Word2VecやGloVeに劣らない
  • 事前学習済みモデルが豊富 → すぐに使える

📝 練習問題

このステップで学んだ内容を確認しましょう。

問題1:GloVeの特徴

GloVeがWord2Vecと最も大きく異なる点はどれですか?

  1. ベクトルの次元数が低い
  2. コーパス全体の共起統計を事前に計算して利用する
  3. サブワード情報を活用する
  4. 未知語に対応できる
正解:b

GloVeの最大の特徴は、グローバルな共起統計を利用することです。

比較:

  • Word2Vec:局所的なウィンドウを独立に処理(予測ベース)
  • GloVe:コーパス全体の共起行列を事前計算(カウントベース)

他の選択肢について:

  • a. 次元数は両方とも同じ(100〜300次元)
  • c. サブワードを使うのはfastText
  • d. 未知語対応もfastTextの特徴

問題2:fastTextの利点

fastTextがWord2VecやGloVeより優れている点として正しくないものはどれですか?

  1. 訓練データにない未知語でもベクトルを生成できる
  2. スペルミスに強い
  3. 学習速度が最も速い
  4. 形態的に似た単語が近いベクトルになる
正解:c

fastTextは学習速度が遅いです。

学習速度の比較:

  • GloVe(速い)> Word2Vec(普通)> fastText(遅い)

fastTextが遅い理由:
単語だけでなく、サブワード(文字n-gram)も学習するため、 ベクトル数が多くなり計算量が増えます。

a, b, d はfastTextの正しい利点です。

問題3:サブワード情報

fastTextで、単語”playing”を文字3-gram(トライグラム)に分割したとき、含まれるものはどれですか?
※ <と>は単語の境界を示す特殊記号

  1. pl
  2. lay
  3. pla
  4. b と c の両方
正解:d

“<playing>”の文字3-gramは:

  • <pl, pla, lay, ayi, yin, ing, ng>

各選択肢について:

  • a. “pl” → 2文字なので3-gramには含まれない ❌
  • b. “lay” → p[lay]ing なので含まれる ✅
  • c. “pla” → <[pla]ying なので含まれる ✅
  • d. b と c の両方 → 正解 ✅

問題4:使い分け

次のシナリオで最も適切な単語埋め込み手法はどれですか?
シナリオ:Twitterのツイートから感情分析を行いたい。ツイートにはスペルミスや新しいスラングが多く含まれる。

  1. Word2Vec
  2. GloVe
  3. fastText
  4. どれでも同じ
正解:c

このシナリオではfastTextが最適です。

理由:

  • スペルミスに強い:サブワード情報で類似性を保持
  • 新しいスラング(未知語)に対応:訓練データにない単語もベクトル生成可能
  • SNSデータに適している:口語的表現や新語が多い環境で効果的

Word2VecとGloVeは未知語に対応できないため、 スペルミスや新語でエラーになってしまいます。

📝 STEP 6 のまとめ

✅ このステップで学んだこと
  • GloVe:共起行列を使ったグローバルな学習(カウントベース)
  • 共起行列:単語ペアの共起回数をまとめた表
  • fastText:サブワード(文字n-gram)で未知語に対応
  • サブワード:単語を文字の並びに分解して学習
  • 3つの手法の比較:それぞれの長所と短所
  • 使い分け:実務ではfastTextが最も汎用的
💡 単語埋め込みの進化

Word2Vec(2013)
→ 予測ベース、局所的な文脈

GloVe(2014)
→ カウントベース、グローバルな統計

fastText(2016)
→ サブワード情報、未知語対応

しかし、これらは全て静的埋め込みです。 単語ごとに1つのベクトルしか持てません。

🎯 次のステップの準備

次のSTEP 7では、コンテキスト化された埋め込み(ELMo)を学びます。

Word2Vec、GloVe、fastTextは静的埋め込み (単語ごとに1つのベクトル)でしたが、 ELMoは文脈に応じて異なるベクトルを生成します。

例:”bank”が「銀行」の意味か「川岸」の意味かで、 異なるベクトルを生成できるようになります! これがBERTへの重要な橋渡しとなります。

📝

学習メモ

自然言語処理(NLP) - Step 6

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE