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

第 4 課:詞袋、TF-IDF 和 N-gram — 經典方法

詞袋模型。 TF-IDF 加權和數學直覺。用於語言建模的 N 元語法。 CountVectorizer 和 TfidfVectorizer 與 scikit-learn。優點和缺點以及什麼時候仍然有效?

🧠 人工智慧與機器學習 — 第 3 課 第 4 課:詞袋、TF-IDF 和 N-gram — 經典方法

NLP 從基礎到進階:掌握自然語言處理

第 2 部分:語言表示-從 BoW 到詞嵌入

亞洲開發網

簡介

在 Word2Vec 和 Transformer 之前,NLP 依賴簡單但令人驚訝的有效字數統計方法。到 2026 年,詞袋和 TF-IDF 仍然被廣泛使用——尤其是當您需要快速基線或小數據時。


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(詞頻):文件中頻繁出現的單字→對該文件很重要
  • 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 什麼時候還「好」?

  • 文字搜尋/資訊檢索
  • 關鍵字擷取
  • 基線分類 小資料集(< 10K 樣本)
  • 特徵工程與深度學習結合

3.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-gram 幫助 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-gram取得本地脈絡詞彙爆炸與BoW/TF-IDF結合

下一篇文章

第 5 課:單字嵌入 — Word2Vec、GloVe、FastText — Leap:用密集的有意義向量表示單詞,其中「國王 - 男人 + 女人 ≈ 女王」。