Chuyển đến nội dung chính

レッスン 4: Bag of Words、TF-IDF、N グラム — 古典的な方法

バッグ・オブ・ワーズモデル。 TF-IDF 重み付けと数学的直観。言語モデリング用の N グラム。 scikit-learn を使用した CountVectorizer と TfidfVectorizer。メリットとデメリット、そしていつから効果があるのか​​?

🧠 AI と ML — レッスン 3 レッスン 4: Bag of Words、TF-IDF、N グラム — 古典的な方法

NLP の基礎から上級まで: 自然言語処理をマスターする

パート 2: 言語表現 — BoW から Word 埋め込みまで

xdev.asia

はじめに

Word2Vec と Transformer が登場するまで、NLP はシンプルだが驚くほど効果的な 単語カウント 手法に依存していました。 Bag of Words と TF-IDF は、特に高速のベースラインや小規模なデータが必要な場合に、2026 年現在でも広く使用されています。


1. バッグ・オブ・ワーズ (BoW)

アイデア

各ドキュメントを、順序を無視した、単語の頻度カウント ベクトルで表します。

from sklearn.feature_extraction.text import CountVectorizer

corpus = [
    "NLP rất thú vị",
    "Machine Learning rất hay",
    "NLP và Machine Learning bổ trợ nhau",
]

vectorizer = CountVectorizer()
X = vectorizer.fit_transform(corpus)

print(vectorizer.get_feature_names_out())
# ['learning', 'machine', 'và', 'nlp', 'nhau', 'bổ', 'hay', 'rất', 'thú', 'trợ', 'vị']

print(X.toarray())
# [[0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1],  ← "NLP rất thú vị"
#  [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0],  ← "ML rất hay"
#  [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0]]  ← "NLP và ML bổ trợ nhau"

制限事項

  • 順序が間違っています: 「犬が人を噛む」 = 「人が犬を噛む」
  • 疎行列: 非常に疎なベクトル (ほとんど = 0)
  • 意味を表すものではありません: 同義語には異なるベクトルがあります

2. TF-IDF (用語頻度 – 逆文書頻度)

直感

  • TF (Term Frequency): 文書内で頻繁に出現する単語 → その文書にとって重要
  • IDF (逆ドキュメント頻度): 単語が 少ないドキュメントに出現する → より重要 (識別)

$$TF\text{-}IDF(t, d) = TF(t, d) \times IDF(t) = \frac{f_{t,d}}{\sum_{t'} f_{t',d}} \times \log\frac{N}{n_t}$$

from sklearn.feature_extraction.text import TfidfVectorizer

corpus = [
    "NLP xử lý ngôn ngữ tự nhiên",
    "Machine Learning học từ dữ liệu",
    "NLP kết hợp Machine Learning để xử lý ngôn ngữ",
]

tfidf = TfidfVectorizer()
X = tfidf.fit_transform(corpus)

# TF-IDF values — từ "xử" và "lý" có IDF thấp vì xuất hiện nhiều docs
import pandas as pd
df = pd.DataFrame(X.toarray(), columns=tfidf.get_feature_names_out())
print(df.round(2))

TF-IDF がまだ「良好」なのはいつですか?

  • テキスト検索/情報検索
  • キーワード抽出
  • ベースライン分類 小規模なデータセット (< 10,000 サンプル)
  • 特徴エンジニアリングと深層学習の組み合わせ

3. Nグラム

アイデア

個々の単語を考慮する代わりに、連続する n 個の単語のシーケンスを考慮してください。

N名前例 (「NLP はクールです」)
1ユニグラム「NLP」「とても」「面白い」「おいしい」
2バイグラム「NLPはとても」「とても興味深い」「興味深い」
3トリグラム「NLPはとても興味深いです」、「とても興味深いです」
from sklearn.feature_extraction.text import CountVectorizer

# Bigram + Unigram
vectorizer = CountVectorizer(ngram_range=(1, 2))
X = vectorizer.fit_transform(["NLP rất thú vị và hay"])
print(vectorizer.get_feature_names_out())
# ['hay', 'nlp', 'nlp rất', 'rất', 'rất thú', 'thú', 'thú vị', 'và', 'và hay', 'vị', 'vị và']

N グラムは、BoW/TF-IDF が 語順 の一部をキャプチャするのに役立ちます。「興味深い」には「興味深い」とは異なる意味があります。


4. アプリケーション: TF-IDF によるテキスト分類

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report

# Dataset ví dụ
texts = [
    "GPU mới của NVIDIA rất mạnh",
    "Giá Bitcoin tăng vọt hôm nay",
    "Đội tuyển Việt Nam thắng 3-0",
    "Transformer architecture cải tiến NLP",
    "Chứng khoán phục hồi sau phiên giảm",
    "World Cup 2026 sẽ tổ chức tại 3 nước",
    # ... thêm data
]
labels = ["tech", "finance", "sports", "tech", "finance", "sports"]

# Pipeline
tfidf = TfidfVectorizer(ngram_range=(1, 2), max_features=5000)
X = tfidf.fit_transform(texts)

model = LogisticRegression()
model.fit(X, labels)

# Predict
new_text = ["Apple ra mắt iPhone mới"]
prediction = model.predict(tfidf.transform(new_text))
print(prediction)  # ['tech']

概要

方法利点制限事項使用例
ボウシンプル、速い秩序の喪失、まばらベースライン、単語数
TF-IDF重要性を考慮する秩序の喪失、まばら検索、キーワード、分類
Nグラムローカルコンテキストの取得語彙爆発BoW/TF-IDFとの組み合わせ

次の記事

レッスン 5: 単語の埋め込み — Word2Vec、GloVe、FastText — Leap: 「王 - 男性 + 女性 ≈ 女王」の意味のある密集したベクトルで単語を表現します。