【個人上課筆記】2026 TAICA 自然語言處理 - 第三周

Hello Guys I’m LukeTseng. 本篇筆記主要紀錄跟統整上課內容,性質屬於個人學習用途,敬請斟酌參考,謝謝。

清大 MOOCS 2026 TAICA 自然語言處理課程網址:https://mooc.nthu.edu.tw/course/info/470

為什麼需要 LSA / LSI?

  • 潛在語意分析(Latent Semantic Analysis, LSA)
  • 潛在語意索引(Latent Semantic Indexing, LSI)

傳統搜尋方法常依靠「字詞完全匹配」(exact match),例如,使用者搜尋:open-source database,傳統方法會傾向尋找同時出現 open-source 和 database 的文件。

但自然語言並非只靠完全相同的字詞表達意思,因此會出現兩個問題。

  1. 有出現,不見得相關:某個字出現在文件中,不代表文件真正討論的是使用者想找的概念,這部分與一詞多義有關,同一個字在不同文章中,可能代表不同領域或概念。
    • 例如 database 可以出現在:MySQL database、genome database。
    • 雖然兩者都有 database,但前者偏向電腦軟體,後者偏向生物資訊,所以有相同的字詞,不代表語意一定相同。
  2. 沒出現,不見得無關:一篇文章即使沒有出現查詢中的字詞,也可能與查詢概念有關。
    • 例如搜尋 Linux OS,某篇文章只寫:Debian 3.0 Woody released
    • 雖然沒有直接出現 Linux,但 Debian 本身與 Linux 作業系統高度相關,所以沒有出現完全相同的字詞,不代表文件與查詢無關,這也是同義詞、近義詞及相關概念所造成的問題。

LSA / LSI 的核心想法

LSI 的目標是透過大量文件中的共現關係,找出字詞與文件背後的隱藏結構。

這是一種統計方法(statistical technique)、資料驅動方法(data-driven method)、使用線性代數中的 SVD。

其基本上的推論為:如果兩個字經常和相同的一組字或文件一起出現,它們可能具有某種語意關係。

例如用人際關係來當比喻:如果兩個人共同認識很多相同的同學,即使兩人沒有直接接觸,他們之間也可能存在某種關聯。

對應到文字資料,就是如果兩個字經常出現在相似的文件環境中,它們的概念可能相關。

當然,單次共同出現可能只是巧合,但在大量資料中重複觀察,就比較可能找出穩定的關係。

建立字詞:文件矩陣

首先需要把文件轉換成矩陣。

有以下十篇文件:

  • Linux/軟體相關文件
    • d1:Indian government goes for open-source software
    • d2:Debian 3.0 Woody released
    • d3:Wine 2.0 released with fixes for Gentoo 1.4 and Debian 3.0
    • d4:gnuPOD released: iPOD on Linux with GPLed software
    • d5:Gentoo servers running at open-source mySQL database
  • DNA/基因相關文件
    • d6:Dolly the sheep not totally identical clone
    • d7:DNA news: introduced low-cost human genome DNA chip
    • d8:Malaria-parasite genome database on the Web
    • d9:UK sets up genome bank to protect rare sheep breeds
    • d10:Dolly’s DNA damaged

從內容上可以大致看出兩個主題:

  • Linux 與開放原始碼軟體。
  • DNA、基因體與複製羊。

其中 database 比較特殊,因為它同時出現在這兩篇裡面:

  • d5:MySQL database
  • d8:genome database

也就是說,database 跨越了兩個不同的主題。

矩陣中的數字代表什麼?

【個人上課筆記】2026 TAICA 自然語言處理 - 第三周 - 矩陣中的數字代表什麼?

Image Source:TAICA MOOCs | 自然語言處理 | 高宏宇老師 | 3-1 投影片

投影片建立的是字詞-文件矩陣(term-document matrix)。

  • 每一列代表一個字詞。
  • 每一欄代表一篇文件。
  • 數值代表該字詞在文件中出現的次數。

看到投影片的矩陣:

  • open-source 出現在 d1、d5,因此是 1。
  • Linux 只出現在 d4。
  • released 出現在 d2、d3、d4。
  • DNA 在 d7 中出現兩次,因此該格為 2。

這個矩陣最初是由 0、1 或詞頻所構成:

  • 0:沒有出現
  • 1:出現一次
  • 2:出現兩次

為什麼矩陣非常稀疏?

一篇文件只會用到整個詞彙庫中的少數字詞,假設詞彙庫有十萬個字,一篇文章可能只使用其中幾百個字,因此在矩陣中,大部分位置都是 0。

以這個例子來看:

  • 前五篇主要談 Linux,所以 DNA、genome、sheep 等位置大多是 0。
  • 後五篇主要談基因,所以 Linux、Debian、Gentoo 等位置大多是 0。

矩陣大致會形成兩個區塊,但 database 可能同時在兩個區塊中出現。

利用 SVD 找出隱藏概念

建立字詞-文件矩陣後,LSI 對矩陣進行奇異值分解(SVD),假設原始矩陣為:$$X$$

SVD 會將它拆成三個矩陣:$$X = U \Sigma V^T$$

  • UU:描述字詞與隱藏結構之間的關係。
  • Σ\Sigma:奇異值組成的對角矩陣。
  • VTV^T:描述文件與隱藏結構之間的關係。

其中最重要的是中間的 Σ\Sigma,這是一個對角矩陣,對角線上的奇異值代表不同成分的重要程度。

只保留最重要的 K 個成分

在投影片中的奇異值為:$$\Sigma = \text{diag}(2.57, 2.49, 1.99, 1.90, 1.68, 1.53, 0.94, 0.66, 0.36, 0.10)$$

前面的值較大,代表它們對原始資料的結構影響較大。

範例設定 K=2K = 2,也就是只保留前兩個最大的奇異值,其他全部設為 0:$$\hat{\Sigma} = \text{diag}(2.57, 2.49, 0, 0, 0, 0, 0, 0, 0, 0)$$

接著再把矩陣乘回去:$$\hat{X} = U \hat{\Sigma} V^T$$

最後得到新的近似矩陣 X^\hat{X}

上述過程稱為降維(dimensionality reduction),只保留最重要的結構,忽略較不重要或較像雜訊的成分。

新矩陣和原始矩陣有什麼差別?

原始矩陣中的數值,代表字詞實際出現次數。

例如在原始矩陣中,database 只出現在 d5、d8 這兩個文件,所以數值為:[0,0,0,0,1,0,0,1,0,0]

但經過 SVD、保留前兩個成分並重建後,database 這一列可能變成:[0.17,0.14,0.19,0.21,0.14,0.04,0.25,0.11,0.09,0.12]

這些數字不再代表實際出現幾次,而代表在保留主要隱藏結構後,這個字詞與各篇文件之間的關聯分數。

即使 database 沒有實際出現在 d1,重建後仍可能得到 0.17。

原因是 d1 有 open-source、d5 同時有 open-sourcedatabase,因此模型從整體共現關係推測,d1 與 database 可能具有一定關係,這就是 LSI 能突破 exact match 的原因。

為什麼沒有出現的字也能得到分數?

以 Linux 為例,原始資料中,Linux 只直接出現在 d4,但:

  • d4 有 software、released
  • d2、d3 也有 released
  • d3 有 Debian、Gentoo
  • d5 有 Gentoo、open-source

因此,透過這一連串的共同出現關係,LSI 可能推測 d2、d3、d5 雖然未直接寫 Linux,但它們與 Linux 主題有關,於是新的矩陣中,Linux 在這些文件上也可能得到分數。

換句話說,LSI 不只是看這篇文章有沒有出現 Linux?而是進一步看這篇文章所使用的其他字詞,是否符合 Linux 相關文件的整體模式?

為什麼數值可能變大、變小,甚至變成負數?

矩陣經過 SVD 降維後,是利用少數成分重新近似原始資料。

因此新的數字可能會有以下這些結果:

  • 從 0 變成正數
  • 從 1 變成小於 1 的數
  • 比原本更高
  • 變成負數

這些數字已經不是實際詞頻,所以不應解讀成某個字出現了負 0.03 次。

負值只是矩陣運算後產生的關聯表示,表示在目前保留的低維結構中,它的方向或關係與某個概念有所不同。

在這裡只需知道重建後的矩陣是語意關聯分數,不再是單純的字詞出現次數。

LSI 如何用於文件檢索?

傳統方法會把每篇文件存成由 0、1 或詞頻構成的向量。

然後查詢也被轉成相同詞彙空間中的向量,再比較查詢與文件是否相似,但問題是,這種方法非常依賴相同字詞的出現。

經過 LSI 後,文件改用新矩陣中的向量表示:x^i\hat{x}_i 新的文件向量不再只有 0 和 1,而轉為包含大小不同的分數、原本為 0、重建後出現的關聯值、少量負值等等,所以就能在新的矩陣空間中進行相似度比較。

LSI 能讓搜尋系統找到字面上不完全相同、但在概念上相近的文件,所以 LSI 的主要作用是:將字詞層級的比對,擴充成概念或潛在語意層級的比對。

LSI 的主要問題

雖然這個方法能處理部分完全匹配的問題,但它的擴展性(scalability)不好。

  1. 矩陣非常大:假設有十萬個字詞跟十萬篇文件,字詞-文件矩陣可能達到 100000×100000100000×100000 ,即使大多數位置是 0,整體規模仍然非常龐大。
  2. 矩陣非常稀疏:大部分字詞不會出現在大部分文件中,所以矩陣包含大量的 0,雖然稀疏矩陣有專門的儲存方式,但仍會增加運算與處理上的困難。
  3. SVD 的運算成本很高:LSI 必須對大型矩陣執行 SVD,小型矩陣可以直接計算,但當矩陣擴大到數萬或數十萬個維度時,直接完整分解會非常耗時,甚至難以完成。

SVD 可以用於降維,但其計算成本很高,這是 LSI 不容易大規模使用的主要原因。

新增字詞可能影響整個矩陣

如果詞彙庫增加一個新字詞,矩陣就會新增一個維度。

由於 SVD 是根據整個矩陣的結構進行分解,因此資料改變時,原本的分解結果也可能受到影響。

意即它不像是簡單的索引,可以很輕易地只加入一筆新資料,一旦加入新資料後整個語意空間可能需要重新計算。

為什麼以前會提出這個方法?

這個方法是在網際網路尚未全面普及的年代發展出來的。

當時網路文件量還沒有今天這麼龐大,搜尋範圍可能只是小型或封閉的文件集合,再加上運算的資料規模較有限。

因此,如果應用在小型文件庫、特定領域文章、封閉環境、文件量相對固定的資料集等等,LSI 仍可能具有實用性。

但是當 Internet 興起、網頁內容快速成長後,巨大字詞-文件矩陣和昂貴的 SVD 計算,就讓這個方法難以擴展。

LSI 的想法具有意義,但不適合處理規模非常大的動態資料。

機率式語言模型與 Word2Vec:CBOW、Skip-gram

此節主要有兩個重點:

  1. 語言模型(Language Model)如何用機率描述具有前後順序的資料。
  2. Word2Vec 如何透過「預測字詞」學習字詞向量,其中包含 CBOW 與 Skip-gram 兩種模型。

複習:何謂語言模型?

語言模型的基本目標是根據目前看到的字詞,估計某個字詞出現的機率。

例如,模型看到這句「今天下午可能會下……」,會推測合理的下一個字可能是:「雨」、「雪」、「冰雹」,其中「雨」可能具有最高機率。

因此,語言模型本質上是在描述字詞序列之間的機率關係。

為什麼使用條件機率?

語言是一種序列資料(sequential data),一個字是否適合出現,通常和它前面的內容有關。例如:「我早上喝了一杯……」,後面出現「咖啡」很合理,但出現「電腦」就比較不合理。

這件事情可以表示成條件機率:$$P(\text{咖啡} \mid \text{我早上喝了一杯})$$

意思是已知前面出現「我早上喝了一杯」時,下一個字是「咖啡」的機率。

因此,語言模型通常會用條件機率描述序列中的前後依賴關係。

語言模型不一定只能處理文字

雖名為「語言模型」,但其實它描述的其實是:具有前後順序與邏輯關係的序列模式。

只要資料具有 sequential pattern,就有機會使用類似語言模型的方式進行描述,例如以下這兩個例子:

1. 機器手臂的動作序列

例如有條機器手臂正執行一項任務,可能會依序進行以下這些步驟:

  1. 舉起手臂
  2. 向右移動
  3. 對準物體
  4. 調整力道
  5. 抓取物體

這些動作不能隨意交換順序。

例如,在尚未對準物體前就進行抓取,會很不合理,所以s前一個動作會影響下一個動作的可能性。

這可以概念性地表示為:$$P(\text{抓取} \mid \text{舉起、移動、對準、調整力道})$$

2. 自駕車的感測器與駕駛行為

自駕車上有許多感測器,例如:影像感測器、速度感測器、方向控制訊號、煞車與力量控制訊號等等,這些訊號會隨時間形成序列。

例如車輛看到紅燈時,可能依序發生這些步驟:

  1. 辨識前方紅燈
  2. 降低速度
  3. 啟動煞車
  4. 停止車輛

駕駛人準備轉彎時,也會先做以下這些動作:

  1. 降低速度
  2. 轉動方向盤
  3. 完成左轉或右轉

這些都是具有前後關係的 sequential pattern,所以,只要資料的順序具有規律,就可以用條件機率描述:$$P(\text{下一個狀態} \mid \text{先前狀態})$$

最簡單的語言模型:Unigram Model(即 Unary Language Model)

在上課投影片中的第一種模型稱為 Unary language model,概念上就是常見的 Unigram language model,此模型把整個句子的機率寫成:$$P(w_1, \dots, w_n) = \prod_i P(w_i)$$

這個公式的意思是:整個句子的機率,是每一個字各自出現機率的乘積。這個模型假設每個字彼此獨立。

例如此句 the cat licked its fur,Unigram 模型會計算:$$P(\text{the}) \times P(\text{cat}) \times P(\text{licked}) \times P(\text{its}) \times P(\text{fur})$$

但這模型完全不考慮字詞順序,所以下面兩個序列可能得到相同的機率:

  • the cat licked its fur
  • fur its licked cat the

因為兩個句子包含相同的字,只是排列順序不同。

因此不考慮字詞順序是不合理的,語言的語意和文法高度依賴順序,若只使用單一字詞機率,無法妥善描述語言。

Bigram Model(即 Binary Language Model):考慮前一個字

在上課投影片中的 Binary language model,概念上對應到 Bigram language model,其公式為: $$P(w_1, \dots, w_n) = \prod_i P(w_i \mid w_{i-1})$$

這個模型不再像 Unigram 將每個字視為完全獨立,而是假設現在這個字的機率,主要由前一個字決定。

例如:the cat licked its fur,可以計算成:$$P(\text{cat} \mid \text{the})$$$$P(\text{licked} \mid \text{cat})$$$$P(\text{its} \mid \text{licked})$$$$P(\text{fur} \mid \text{its})$$

與 Unigram 相比,Bigram 考慮了字詞順序,例如 P(furits)P(\text{fur} \mid \text{its})P(furcomputer)P(\text{fur} \mid \text{computer}) 更合理。

Bigram 的限制

Better but still limited by short context distance.

Bigram 雖然比 Unigram 好,但它只考慮前一個字,因此上下文範圍非常短。

例如:The cat that I saw yesterday licked its fur.

當模型判斷 licked 時,如果只看前一個字 yesterday,就無法直接得知真正執行舔舐動作的是前面的 cat

所以 Bigram 最主要的問題是,它只能使用非常短的上下文資訊。

Word2Vec 的兩種模型

Word2Vec 主要有兩種模型:

  1. Continuous Bag of Words,CBOW
  2. Skip-gram

兩者使用的資料相同,但預測方向相反。

什麼是 Context Window?

到了 Word2Vec 開始設定一個視窗大小(window size) mm,假設目前的中心字位於位置 cc,中心字為 ωc\omega_c,則模型會考慮中心字左邊與右邊的字:$$w_{c-m}, \dots, w_{c-1}, w_{c+1}, \dots, w_{c+m}$$

例如這句 The cat licked its fur,假設中心字是 licked,且視窗大小 m=1m = 1,那只看中心字相鄰的兩個字:

  • 左側 context:cat
  • 中心字:licked
  • 右側 context:its

即:cat [licked] its

CBOW:由前後文預測中間字

CBOW 的全名為 Continuous Bag of Words,其預測方向為:已知中心字附近的前後文,預測中間的中心字。

公式:$$P(w_c \mid w_{c-m}, \dots, w_{c-1}, w_{c+1}, \dots, w_{c+m})$$

  • ωc\omega_c 是要預測的中心字。
  • 其他字是中心字附近的上下文。

繼續拿前面那句 The cat licked its fur 當例子,先將中心字 licked 暫時拿掉:The cat [ ] its fur.

CBOW 會看到周圍的字,發現前面有 The cat、後面有 its fur,然後預測中心字最可能是什麼,也就是估計:$$P(\text{licked} \mid \text{The, cat, its, fur})$$

若 window size mm 設為 1,則會只看相鄰字,P(lickedcat, its)P(\text{licked} \mid \text{cat, its})

最後 CBOW 可以簡單記成「看周圍,猜中間。」

CBOW 的輸入與輸出

cat [licked] its 為例,輸入是 cat,its 輸出是 licked

圖示可以寫成 [cat,its]licked[\text{cat},\text{its}]⟶\text{licked}

Skip-gram:由中間字預測前後文

Skip-gram 與 CBOW 相反,其預測方向是:已知中心字,預測它周圍可能出現哪些字。公式為:$$P(w_{c-m}, \dots, w_{c-1}, w_{c+1}, \dots, w_{c+m} \mid w_c)$$

  • ωc\omega_c 是已知的中心字。
  • 其他字是要預測的上下文

假設已知中心字 licked,模型要預測它左右可能出現:cat(左) 跟 its(右),可理解成:P(cat, itslicked)P(\text{cat, its} \mid \text{licked}),圖示為 licked[cat,its]\text{licked} ⟶ [\text{cat},\text{its}]

所以 Skip-gram 可以簡單記成「看中間,猜周圍。」

CBOW 與 Skip-gram 的差異

兩者的差異只在預測方向:

模型已知資訊預測目標
CBOW周圍的 context中心字
Skip-gram中心字周圍的 context

為什麼這種預測方式可以學到字詞關係?

假設模型讀過大量句子:

The cat licked its fur.
The dog licked its paw.
The cat cleaned its fur.

在這些句子中:

  • cat 和 dog 的周圍字詞可能相似。
  • fur 和 paw 的使用環境可能相似。
  • licked 和 cleaned 也可能出現在相近的語境中。

當模型不斷執行「用中心字猜上下文」或「用上下文猜中心字」時,就會逐漸學到哪些字經常出現在相似環境。

Word2Vec 的核心精神是:字詞的意義,可以從它經常出現的上下文模式中學習。

不需要透過人工直接告訴模型 cat 和 dog 很相似,模型會透過大量語料中的前後文關係,自己學到它們具有相似的使用模式。

條件機率與 Word2Vec 的關係

從數學上來看,CBOW 與 Skip-gram 都可以寫成條件機率。理論上,如果已經統計大量語料,也可以直接計算字詞共同出現的條件機率。

但 Word2Vec 並不是單純直接使用這種條件機率統計方式,也就是說,條件機率是用來理解它的預測目標,而 Word2Vec 實際上會使用另一種模型與訓練方式進行學習。

Skip-gram 的訓練資料與模型參數

此節接續前面的 Word2Vec,重點如下:

  1. Skip-gram 如何把語料庫轉換成訓練資料。
  2. 這些訓練資料如何送入一個只有單一隱藏層的神經網路。
  3. Word embedding 實際上是從神經網路的權重矩陣中取出的,而不是直接人工定義的。

如何從語料庫建立訓練資料?

94def152-4f55-46d1-98ce-48ab33c38df0

Image Source:TAICA MOOCs | 自然語言處理 | 高宏宇老師 | 3-2 投影片

在上課投影片中的語料是 The cat licked its fur. The truck moved.,並設定 window=1,代表對每個中心字,只考慮左邊相鄰的一個字跟右邊相鄰的一個字。

因此,語料會被切成許多「中心字-上下文字」配對,就像圖中的那個表一樣:

CenterContext
thecat
catthe
catlicked
lickedcat
lickedits
itslicked
itsfur
furits
thetruck
truckthe
truckmoved
movedtruck

例如句子片段 the cat licked,當 cat 是中心字時,它的相鄰字有左邊的 the 跟右邊的 licked,所以會形成兩筆訓練資料:

  1. (cat,the)
  2. (cat,licked)

兩筆資料會分開送入模型,不是一次同時要求模型輸出兩個字。

即使 window 大於 1,仍然一次只輸入兩個字

假設 window=2,中心字 licked 周圍可能有 the cat [licked] its fur,則可以產生:

  1. (licked,the)
  2. (licked,cat)
  3. (licked,its)
  4. (licked,fur)

window 越大,產生的 word pair 越多,但每一筆送進 Skip-gram 模型的資料仍然只有一個中心字作為輸入,一個 context 字作為正確答案。

為什麼這是監督式訓練資料?

每一筆訓練資料都已經知道輸入是什麼字、正確輸出是什麼字,例如 (cat,licked) 代表:

  • 輸入:cat
  • 正確答案:licked

因此從神經網路訓練的角度來看,它具有明確的輸入與標籤,可以視為一個預測或分類問題。

為何 Word2Vec 可視為 Self-supervised Learning?

Skip-gram 雖然具有輸入與正確答案,例如 (cat,licked)(\text{cat},\text{licked}) ,但這些標籤並不是人工逐筆標註的,而是從原始語料中自動產生。

模型不需要人工提供哪些字是名詞或動詞、哪些字代表動物、文章的情緒標籤、字詞的語意分類等等,只需要原始文章,就能利用文章本身產生輸入和正確答案。

因此,從訓練形式來看,這是一個監督式預測問題;但從資料標籤的來源來看,它屬於自我監督學習(Self-supervised Learning)。

其核心精神是模型從資料本身建立預測任務,再透過這個任務學習有用的表示。

這個概念也可類比到 BERT,例如:克漏字預測Next Sentence Prediction

這些方法同樣不需要人工直接標註語意,只需利用原始文本來自動建立訓練目標。

Skip-gram 使用的神經網路結構

【個人上課筆記】2026 TAICA 自然語言處理 - 第三周 - Skip-gram 使用的神經網路結構

Image Source:https://mccormickml.com/2016/04/19/word2vec-tutorial-the-skip-gram-model/

投影片中的 Word2Vec 是一個淺層前饋神經網路(feedforward neural network),其結構為:$$\text{Input Layer}→\text{Hidden Layer}→\text{Output Layer}$$

這個 NN 只有一層 hidden layer,而其中包含兩個主要的權重矩陣:

  • Input 到 hidden layer 的矩陣
  • Hidden layer 到 output 的矩陣

這兩個矩陣都是模型在訓練過程中要學習的參數。

輸入層:用 one-hot vector 表示字詞

假設詞彙庫共有 V=10000V=10000 個不同字詞,那每個輸入字都會用長度為 10000 的 one-hot vector 表示。

例如,假設 cat 在詞彙表中的位置是第 7 個:$$x_\text{cat}=[0,0,0,0,0,0,1,0,…,0]$$

其特性為:

  • 只有 cat 對應的位置是 1。
  • 其他 9999 個位置都是 0。

所以不同字詞的 one-hot vector 只是在不同位置放置 1。

Input 到 Hidden Layer:從 10000 維轉換成 300 維

在上圖中假設 hidden layer 有 D=300D=300 個 neuron,因此模型會將長度 10000 的 one-hot vector,轉換成長度 300 的向量。

第一個權重矩陣可以表示為:$$W_{in} \in \mathbb{R}^{10000 \times 300}$$

輸入向量經過這個矩陣後,得到 hidden layer:$$h=xW_\text{in}$$

  • xx 是長度 10000 的 one-hot vector
  • hh 是長度 300 的 hidden vector

one-hot vector 乘矩陣,等同在選取一列

假設 xcat=[0,0,1,0,,0]x_\text{cat}=[0,0,1,0,…,0],因為只有 cat 對應的位置是 1,所以執行 h=xcatWinh = x_\text{cat}W_\text{in} 實際效果就是從 WinW_\text{in} 中選出 cat\text{cat} 對應的那一列。

因此 h=vcath=v_\text{cat} 這一列包含 300 個數字,就是 cat\text{cat} 的輸入 embedding vcat=[v1,v2,,v300]v_\text{cat}=[v_1,v_2,…,v_{300}]

同理:

  • dog 會選到另一列。
  • truck 會選到另一列。
  • 每一個字都有自己的 300 維向量。

所以第一個矩陣可以視為一張 embedding 查詢表:$$W_{\text{in}} = \begin{bmatrix} v_1 \ v_2 \ \vdots \ v_{10000} \end{bmatrix}$$

每一列都是一個字的 embedding。

Hidden Layer 的 300 個數字代表什麼?

將原本長度為 10000 的 one-hot vector,轉換成長度為 300 的向量表示。這 300 個數字不是人工指定的「名詞、動詞、動物、顏色」等明確屬性,這些是模型為了完成「預測相鄰字」這個任務,自動學習出來的表示。

例如,若 cat 的 embedding 能讓模型有效預測 the、licked、fur 這些字詞,則 dog 也經常需要預測相似的 context,那麼 cat 與 dog 的 embedding 可能逐漸形成相似的數值結構。

因此這 300 個數字被視為該字詞的:

  • 表示(representation)
  • 概念表示
  • Word embedding

Hidden Layer 到 Output Layer

Hidden layer 得到 300 維向量後,還要透過第二個權重矩陣轉換到輸出層,第二個矩陣可以表示為:$$W_{\text{out}} \in \mathbb{R}^{300 \times 10000}$$

計算 z=hWoutz = hW_\text{out} 會得到長度 10000 的輸出分數 z=[z1,z2,,z10000]z = [z_1, z_2, \dots, z_{10000}] ,每一個位置對應詞彙庫中的一個字。

接著再經過 Softmax,將分數轉換成機率(以下是 Softmax 公式):$$P(w_j \mid w_i) = \frac{e{z_j}}{\sum_{k=1}{10000} e^{z_k}}$$

最後得到以下結果:$$[P(w_1 \mid w_i), P(w_2 \mid w_i), \dots, P(w_{10000} \mid w_i)]$$

這些機率加總為 1。

Embedding 維度越高,不一定越好

Word2Vec 的 embedding 維度,就是 hidden layer 的 neuron 數量,例如 300 個 neuron 對應 300 維 embedding;500 個 neuron 對應 500 維 embedding。

在直覺上可能會認為維度越高,可以儲存的字詞資訊越多,因此效果應該越好,但 embedding 維度增加後,效果不一定會明顯提升。

原因是更多維度雖然提高模型容量,但新增的資訊不一定都是有用的,維度過高還可能增加模型參數量、記憶體需求、訓練計算量、後續向量運算成本等等。

例如,假設詞彙表大小為 10000:

  • 使用 300 維 embedding 時:WoutR300×10000W_{\text{out}} \in \mathbb{R}^{300 \times 10000} ,共有:10000×300=3,000,00010000 \times 300=3,000,000 個參數。
  • 若改成 1000 維:WoutR1000×10000W_{\text{out}} \in \mathbb{R}^{1000 \times 10000} ,參數便增加到:10000×1000=10,000,00010000 \times 1000=10,000,000,然而,參數增加不代表字詞相似度或下游任務的效果會等比例改善。

輸出層在預測什麼?

假設訓練資料是 (cat,licked)(\text{cat}, \text{licked}) ,則:

  • 輸入層的 cat\text{cat} 位置為 1。
  • hidden layer 取得 cat\text{cat} 的 300 維向量。
  • output layer 輸出 10000 個字的機率。
  • 希望 licked\text{licked} 對應位置的機率最高。

例如模型可能輸出:

Context 字預測機率
licked0.40
the0.25
fur0.15
truck0.001
其他字其餘機率

訓練會調整兩個權重矩陣,使正確 context 字的預測機率提高。

計算預測誤差:Cross Entropy Loss

假設一筆 Skip-gram 訓練資料為:

  • 中心字:cat
  • Context 字:licked

詞彙表順序為:the, cat, licked, its, fur, truck, dog, moved

中心字 cat 的輸入 one-hot vector 為 x=[0,1,0,0,0,0,0,0]x=[0,1,0,0,0,0,0,0] ,正確的 context 字 licked 也會表示成 one-hot vector,作為模型的正確答案:y=[0,0,1,0,0,0,0,0]y=[0,0,1,0,0,0,0,0]

假設模型經過 Softmax 後,輸出以下機率分布:y^=[0.1,0.0,0.1,0.3,0.2,0.1,0.1,0.1]\hat{y}=[0.1,0.0,0.1,0.3,0.2,0.1,0.1,0.1]

這代表模型只給正確答案 licked 0.10.1 的機率,因此目前預測並不準確。

而 Word2Vec 使用交叉熵(Cross Entropy)衡量正確答案與模型預測之間的差異:$$CE(\hat{y}, y) = - \sum_{i=1}^{V} y_i \log(\hat{y}_i)$$

所以:

  • 正確 context 字的預測機率越高,Loss 越小。
  • 正確 context 字的預測機率越低,Loss 越大。

因此模型的訓練目標,就是提高正確 context 字的機率,並降低 Cross Entropy Loss。

Positive Data、Negative Data 與資料不平衡問題

從語料庫中依照 window 取得的相鄰字配對,都是實際共同出現的字,因此可視為正樣本(Positive Data)。

例如:(cat,licked)(\text{cat},\text{licked}) 代表 catlicked 確實在指定的 context window 內共同出現。但若詞彙表中共有一萬個字,對中心字 cat 而言,真正出現在附近的字可能只有少數幾個,其他大量字詞都沒有共同出現。

理論上,這些未出現的字可以視為負樣本(Negative Data),但問題是正樣本數量很少,而負樣本數量極多。

例如只有幾個正確 context,卻可能有接近一萬個非 context 字。如果將所有沒有共同出現的字都當作負樣本,會形成嚴重不平衡的訓練資料(少量 Positive Data大量 Negative Data\text{少量 Positive Data}≪\text{大量 Negative Data}

這種不平衡會使模型難以訓練,也可能造成訓練效果不佳。

因此,Word2Vec 不會單純把所有未共同出現的字都當成負樣本,而需要從大量候選負樣本中挑選一部分,以及適當平衡正樣本與負樣本,避免每次都對完整詞彙表進行不必要的訓練。

兩套不同的 Word Embedding

Word2Vec 的兩個權重矩陣其實包含兩套不同的 embedding。

第一套:Input embeddings

Input 到 hidden layer 的矩陣中,每一個字都有一個向量 viv_i 稱為 Input embedding 或 target word embedding。

例如 vcatv_\text{cat} 代表 cat 作為中心字輸入時的向量。

第二套:Output embeddings

Hidden layer 到 output layer 的矩陣中,也存在每個字對應的向量 uiu_i 稱為 Output embedding。

例如 ulickedu_\text{licked} 代表 licked 作為預測目標或 context 字時使用的向量。

因此,同一個字實際上會有兩種表示:

  1. 作為中心字時的 viv_i
  2. 作為 context 字時的 uiu_i

模型如何學習預測?

假設中心字為 wiw_i ,其 input embedding 為 viv_i ,某個候選 context 字為 wjw_j ,以及 output embedding 為 uju_j

模型透過這兩組向量計算該 context 字的分數,然後轉換成機率。

直覺上而言,如果 viv_iuju_j 的組合分數高,模型認為它們容易共同出現;如果分數低,模型認為它們較不容易成為相鄰字。

訓練資料若為 (cat,licked)(\text{cat}, \text{licked}) ,模型就會調整參數使 P(lickedcat)P(\text{licked} \mid \text{cat}) 提高。

若下一筆是 (cat,the)(\text{cat}, \text{the}) ,模型又會調整參數使 P(thecat)P(\text{the} \mid \text{cat}) 提高。

經過大量語料訓練後,cat 的向量便會包含有助於預測其常見 context 的資訊。

為什麼 embedding 可以表達字詞關係?

Word2Vec 有一個前提:如果一組向量能夠有效預測某個字周圍經常出現的字,那麼這組向量就包含了該字重要的使用資訊。

例如:

  • cat 常和 fur、licked、the 出現。
  • dog 可能也常和類似的字出現。
  • truck 則會和 moved、road 等不同字出現。

為了讓預測誤差降低,模型可能會讓 vcatv_\text{cat}vdogv_\text{dog} 這兩個弄得比較接近,而與 vtruckv_\text{truck} 較不相似。

這並非因為模型被直接告知「cat 和 dog 都是動物」,而是因為模型在語料中需要預測相似的上下文。

模型是否真的「理解」文字?

假設一個人讀過大量書籍,當別人說出前幾個字,他就能準確接出後面的內容。

這時可以提出疑問:他是真的理解內容,還是只是很會背或很會預測內容?

Word2Vec 也存在類似問題。

模型可以準確預測上下文字詞,不代表它具有和人類完全相同的語意理解,但在 Word2Vec 的前提中:能夠準確預測上下文所需要的內部表示,可以作為有用的字詞表示。

因此,這裡的「語意」應理解為從大量字詞共同出現模式中學到的統計表示,而非直接宣稱模型能夠真正理解文字。

訓練完成後真正需要的是什麼?

Word2Vec 訓練完成後,並不是為了保留整個「預測相鄰字」的模型,模型訓練的目的,是讓第一個權重矩陣學到有效的字詞表示。

因此,訓練完成後會取出 WinW_\text{in} 這個矩陣。

若詞彙數為 10000、向量維度為 300,則 WinR10000×300W_{\text{in}} \in \mathbb{R}^{10000 \times 300} ,其中每一列就是一個字的 300 維 embedding。

例如:

W_{\text{in}}[\text{cat}] = v_{\text{cat}}$$$$W_{\text{in}}[\text{dog}] = v_{\text{dog}}$$$$W_{\text{in}}[\text{truck}] = v_{\text{truck}}

後續需要某個字的 Word embedding 時,只要查詢這個矩陣中對應的一列即可。

完整訓練流程整理

整個 Skip-gram Word2Vec 流程可以整理如下:

  • 第一步:準備語料庫,例如 The cat licked its fur. The truck moved.
  • 第二步:根據 window 建立 word pairs,例如: (cat,the)(\text{cat}, \text{the})(cat,licked)(\text{cat}, \text{licked})
  • 第三步:把中心字轉成 one-hot vector,如 cat[0,0,1,0,,0]\text{cat}→[0,0,1,0,…,0]
  • 第四步:通過第一個矩陣取得 hidden vector。h=xWinh = xW_\text{in} 得到 300 維向量 h=vcath = v_\text{cat}
  • 第五步:通過第二個矩陣產生輸出分數。z=hWoutz = hW_\text{out}
  • 第六步:透過 Softmax 得到每個字的機率。P(wjwi)P(w_j \mid w_i)
  • 第七步:根據正確 context 調整權重。若正確答案是 licked,就讓 P(lickedcat)P(\text{licked} \mid \text{cat}) 提高。
  • 第八步:訓練完成後取出第一個矩陣 WinW_\text{in} ,其每一列就是一個字的 Word embedding。

那些常見的模型

GloVe:利用全域統計資訊學習字詞向量

GloVe 全名為 Global Vectors for Word Representation。

Word2Vec 已經能從字詞的上下文學到字詞相似性跟向量空間中的規律關係。但 Word2Vec 主要透過中心字與鄰近 context 的預測任務學習,因此著重的是局部上下文關係。

而 GloVe 則進一步考慮整個語料庫中的全域統計資訊(global statistical information),也就是觀察一個字與其他字,在整個語料庫中共同出現的整體情況。

簡單來說可以理解成:

  • Word2Vec:從一次次的局部字詞配對中學習。
  • GloVe:利用整個語料庫累積的共現統計關係學習。

例如,假設 catdog 經常出現在相似的文章、句子或詞語附近,GloVe 會從整體共同出現情況中,將兩者的向量關係拉近。

在這堂課只需要掌握以下兩點,沒有要講太細:

  • GloVe 的主要特色,是把整個語料庫的全域共現統計納入 Word Embedding 的學習。
  • GloVe 也有已經訓練完成的預訓練向量(pre-trained vectors),使用者不一定要自行重新訓練。

FastText:利用單字內部的拼字資訊

FastText 是另一種常見的 Word Embedding 方法。特色是不只把整個單字視為一個不可拆分的單位,也會考慮單字內部的字元層級特徵(character-level features)。

例如英文單字可能具有相似的拼字結構或詞形變化:

  • play
  • plays
  • played
  • playing

即使這些是不同的單字,它們在字母組成上仍有明顯關係。

FastText 可以利用這些拼字與詞形(morphology)模式,建立單字的向量表示。

因此,即使模型沒有直接看過某個完整單字,仍可能根據該字的內部拼字結構,推測其 Word Embedding。

FastText 如何處理 OOV?

OOV 是 Out-of-Vocabulary,詞彙表外單字。

傳統 Word2Vec 會將每個完整單字對應一個固定向量,如果某個字沒有出現在訓練詞彙表中,就找不到對應的 embedding。

例如模型的詞彙表中有 play、played、playing 這些字,但沒有看過 playfully,一般以完整單字為單位的方法,可能無法直接取得 playfully 的向量。

FastText 因為會考慮單字內部的字元與拼字模式,所以可以利用其中已知的部分,對未知字的向量作出估計。

FastText 的優點:即使遇到沒有直接出現在詞彙表中的字,也有機會根據拼字結構產生向量。

英文與中文的差異

不同語言不能完全用相同方式看待。

英文單字具有明顯的拼字與詞形結構,例如字首、字根、字尾、時態變化、單複數變化等等,所以利用 character-level features 推測未見單字,通常具有一定意義。

但中文的組成方式與英文不同,中文不是單純把一連串字母拼成單字,因此英文中有效的拼字規律,不一定能直接套用在中文。

所以同一種 Embedding 方法,在英文、繁體中文、簡體中文或其他語言上的效果可能不同。

此外,即使使用相同演算法,若訓練語料不同,最後得到的 embedding 也會不同。

例如用新聞語料訓練、用社群文章訓練、用古典中文訓練、用醫學文件訓練等等,即使是同一個字,也可能因為語料中的使用方式不同,而得到不同的向量表示。

可以直接使用預訓練的 Word Embedding

Word2Vec、GloVe 與 FastText 都可能有別人已經用過的大型語料訓練完成的向量,這些稱為預訓練詞向量(pre-trained word vectors)。

使用預訓練向量的好處是:

  1. 不必自己收集大量語料。
  2. 不必重新花費大量時間訓練。
  3. 可以直接將字詞轉換成向量。
  4. 可以快速用於後續 NLP 任務。

網路平台上可能找到由不同方法、不同語料與不同語言訓練的 embedding,例如:

  • Word2Vec
  • GloVe
  • FastText
  • 繁體中文向量
  • 簡體中文向量
  • 英文向量
  • 阿拉伯文向量

因此,實際使用時不只是選演算法,也是在選「演算法+訓練語料+語言」。

應該用哪一種 Word Embedding?

視情況而定。

沒有任何一種 Word Embedding 能在所有資料與所有任務中保證最好。

1. GloVe

GloVe 被廣泛使用,也通常能得到不錯的結果。

適合用來取得一般性的預訓練 Word Embedding,並利用語料庫中的全域統計關係表示字詞。

2. FastText

FastText 同樣可以得到不錯的結果。

當資料中可能出現新字、拼字變化、詞形變化、未出現在詞彙表中的字,用 FastText 的 character-level features 可能具有優勢。

3. 自行訓練 Word2Vec

當現有預訓練向量無法涵蓋自己的詞彙時,可以考慮使用自己的語料訓練 Word2Vec。

例如特殊領域可能包含大量一般語料沒有的字:

  • 古典中文
  • 特定學術領域
  • 專業術語
  • 特定公司內部文件
  • 特殊社群用語等等。

這時可能出現許多 OOV,自己需要的字很多,但預訓練向量中沒有這些字,解法之一就是用自己的領域語料重新訓練 Word2Vec,如此得到的向量,能更符合該領域中實際的字詞用法。

為什麼不能只根據一般規則選擇?

有些選擇原則只能作為參考,即使一般認為某個 embedding 表現很好,放到自己的資料上,也不一定仍然最好。

原因有語言不同、語料來源不同、領域不同、詞彙不同、下游任務不同等等這些原因。例如,同一套向量可能在一般英文新聞上表現良好,但不一定適合古典中文分析、醫療文本、程式碼文件等等。

所以建議在自己的特定任務上,實際測試不同的 Word Embedding 來找到最適合自己的 embedding。

如何評估 Word Embedding 的好壞?

研究中通常會用 Benchmark Dataset,也就是基準資料集來比較不同 Word Embedding。

例如 WordSim353 這一個 dataset,這類資料集通常會有「多組字詞配對」、「每一組字詞之間的人工相似度分數」來做測試跟驗證。

建立 embedding 後,可以計算模型認為這些字有多相似,再與資料集提供的相似度分數比較。如果模型產生的字詞關係與基準資料集較一致,代表它在字詞相似度方面的表現較好。

因此,當提出新的 embedding 方法時,可以在相同 Benchmark Dataset 上比較 Word2Vec、GloVe、FastText、自己設計的方法等等這些方法。

也可以直接檢查向量關係

除了用 Benchmark Dataset,也可以在訓練完成後觀察實際向量是否符合預期。

例如檢查:

  • cat 和 dog 是否較接近。
  • cat 和 truck 是否較遠。
  • 相似概念的字是否具有相似向量。

這不單只是看每個向量中單獨的數字,而是觀察不同字詞向量之間的關係。

如果 cat、dog 和 truck 都沒有明顯區別,就表示該 embedding 可能沒有學到預期的字詞關係。

Word Embedding 可以用於下游任務

Word Embedding 訓練完成後,就可以把它視為字詞的數值表示,用於後續任務,而這些後續任務統稱為「下游任務」(downstream tasks)。

在課程中沒有特別去逐一介紹具體任務,重點聚焦在後續模型不必再直接使用 one-hot vector,而可以從 Word Embedding 開始處理文字。

為什麼 Word Vector 比單純 ID 更有用?

若只把字表示成 ID,例如:

  • cat → 2
  • dog → 7
  • truck → 6

這些數字只是識別編號,不能因為 76<72∣7−6∣<∣7−2∣ 就認為 dogtruckdogcat 更相似。

ID 本身沒有語意,也不能用來合理地計算字詞相似度,而 One-hot vector 也有類似問題,它只能區分不同字詞,不能直接表示字詞關係。

Word vector 則不同,每個字會被表示成一組經由資料學習出的數字,這些向量的數值結構可以反映語料中的使用關係。

所以只要文字被轉換成有意義的數值向量,電腦就能進一步進行計算,而不再只是把字當成沒有關係的 ID。

傳統 NLP 的兩個方向

1. 傳統 NLP 的標準流程(SOP in traditional NLP)

主要有:

  1. 結構分析(structural analysis)
  2. 文件表示(document representation)

而結構分析可能涉及文章中字詞的關係、句子的結構、語法關係等等;Parsing Tree 也是一種結構分析工具,可以提供文字之間的某些關係。

2. 字詞的基本理解(Basic word understanding)

也就是將每個字轉換成一個向量,用這組數字表示該字在語料中學到的概念與使用關係。

這裡所說的「理解」並不是說電腦具有像人類一般的理解,而是指電腦不再只把字視為編號,最後把字轉為具有可計算、可比較的向量表示。

N-gram 與 N-gram Language Model

此節主要介紹:

  1. 如何把文字切成 N-gram。
  2. 如何利用語料庫中的出現次數,建立一個以統計方式預測下一個字的語言模型(Language Model)。

這裡介紹的是傳統的計數式語言模型,不是神經網路模型。

什麼是 N-gram?

N-gram 是由連續 NN 個字詞所組成的序列。

假設句子是 Please turn your homework,接著請看以下這些 N-gram 的做法。

Unigram:一次取一個字

Unigram 又稱為 1-gram,它會把每個字詞單獨被視為一個單位,例如分成以下這樣:

  • please
  • turn
  • your
  • homework

Bigram:一次取兩個連續字

Bigram 又稱為 2-gram,也就是一次取兩個連續字詞:

  • please turn
  • turn your
  • your homework

Trigram:一次取三個連續字

Trigram 又稱為 3-gram:

  • please turn your
  • turn your homework

因此,N-gram 中的 N 代表每個片段包含多少個連續字詞。

另一種「使用到 N-gram」的說法

有時候「使用 N-gram」也可能表示從 1-gram 一直使用到 N-gram,例如「使用到 3-gram」可能同時包含 Unigram、Bigram、Trigram 等等,於是就會形成如下的字詞:

1
2
3
4
5
6
7
8
9
10
11
please
turn
your
homework

please turn
turn your
your homework

please turn your
turn your homework

N-gram 與 N-gram Language Model 的差異

N-gram 本身只是文字切割方式,而 N-gram Language Model 則是進一步統計這些片段在語料庫中出現的次數,藉此估計下一個字出現的機率。

以 Bigram Language Model 為例,其核心問題是:已知前一個字,下一個字出現的機率是多少?例如 P(wantI)P(\text{want} \mid \text{I}) ,表示已知前一個字是 I,下一個字是 want 的機率。

從語料庫統計 Bigram

投影片中的語料範例如下:

1
2
3
4
I want to eat lunch.
I want to eat Chinese food.
I don't want to spend time cooking.
...

使用 Bigram 時,要統計所有連續兩字的出現次數。

假設統計結果為:

1
2
3
4
C(I want) = 827
C(want to) = 608
C(to eat) = 686
C(eat lunch) = 42

其中 C 代表某個字詞組合在語料庫中出現的次數。

如何閱讀 Bigram Count Matrix?

【個人上課筆記】2026 TAICA 自然語言處理 - 第三周 - 如何閱讀 Bigram Count Matrix?

Image Source(Stanford University “Speech and Language Processing” 3: N-gram Language Models):https://web.stanford.edu/~jurafsky/slp3/

上圖將 Bigram 次數整理成一個矩陣,這些欄位意義如下:

  • 每一列代表前一個字。
  • 每一欄代表下一個字。
  • 格子中的數字代表這兩個字連續出現的次數。

這張表記錄的是 C(前一個字,下一個字)C(\text{前一個字}, \text{下一個字})

利用相對頻率計算條件機率

一般條件機率的概念為如下公式:$$P(w \mid h) = \frac{C(h, w)}{C(h)}$$

  • ww:要預測的下一個字。
  • hh:已經看過的歷史內容(history)。
  • C(h,w)C(h,w):歷史內容後面接著字 ww 的次數。
  • C(h)C(h):歷史內容出現的總次數。

以 Bigram 為例,history 只保留前一個字,所以 $$P(w_j \mid w_i) = \frac{C(w_i, w_j)}{\sum_{w} C(w_i, w)}$$

分母就是矩陣中該列所有次數的總和。

例如

P(wantI)=C(I want)C(I)P(\text{want} \mid \text{I}) = \frac{C(\text{I want})}{C(\text{I})}

,若 I\text{I} 後面大多數時候接著 want\text{want},這個條件機率就會很高。

History 代表什麼?

P(wh)P(w \mid h) 中的 hh 代表 history,也就是預測目前字詞之前已經出現的內容。

例如要計算「已知 its water is so transparent that,下一個字是 the 的機率」,寫成條件機率的表示為 P(theits water is so transparent that)P(\text{the} \mid \text{its water is so transparent that}) ,可用出現次數表示成:$$P(\text{the} \mid \text{its water is so transparent that}) = \frac{C(\text{its water is so transparent that the})}{C(\text{its water is so transparent that})}$$

  • 分子的意思為完整片段 its water is so transparent that the 出現幾次。
  • 分母則是 its water is so transparent that 出現幾次。

Bigram 模型只保留最後一個字

直接使用完整 history 會遇到資料不足的問題。

因為像 its water is so transparent that,這麼長的完整字串,在語料庫中可能很少出現,甚至完全沒有出現。

Bigram Language Model 因此做了一個簡化假設:下一個字只與前一個字有關。

所以 P(theits water is so transparent that)P(\text{the} \mid \text{its water is so transparent that}) 會被近似成 P(thethat)P(\text{the} \mid \text{that}),也就是忽略較早之前的 its water is so transparent,只留下最接近的前一個字 that

Bigram 模型的基本假設

假設句子為 w1,w2,w3,,wnw_1,w_2,w_3,…,w_n,完整條件機率原本應該是 P(wkw1,w2,,wk1)P(w_k \mid w_1,w_2,…,w_{k−1}) ,但 Bigram 模型會近似為 P(wkwk1)P(w_k \mid w_{k−1}) ,這樣意思是:要預測目前的字,只看前一個字。

例如 I → want → to → eat → lunch,模型會分別計算:

P(\text{want} \mid \text{I})$$$$P(\text{to} \mid \text{want})$$$$P(\text{eat} \mid \text{to})$$$$P(\text{lunch} \mid \text{eat})

機率為 0 會造成什麼問題?

【個人上課筆記】2026 TAICA 自然語言處理 - 第三周 - 機率為 0 會造成什麼問題?

Image Source(Stanford University “Speech and Language Processing” 3: N-gram Language Models):https://web.stanford.edu/~jurafsky/slp3/

假設某個 Bigram 在語料庫中沒有出現 C(wi,wj)=0C(w_i,w_j)=0,那麼 P(wjwi)=0P(w_j \mid w_i)=0,計算整個句子機率時,各個條件機率需要相乘。

因此只要其中一項為 0,整個句子的機率就會變成 0。

Add-k Smoothing

【個人上課筆記】2026 TAICA 自然語言處理 - 第三周 - Add-k Smoothing

Image Source(Stanford University “Speech and Language Processing” 3: N-gram Language Models):https://web.stanford.edu/~jurafsky/slp3/

為了避免機率為 0,可以使用平滑(Smoothing),例如這邊使用的是:Add-k smoothing,其中 k=1。

k=1 時,也就是每個 Bigram 計數都加 1:$$C’(w_i, w_j) = C(w_i, w_j) + 1$$

所以就可以看到上表中原本 0 的地方都變成 1 了,如此一來,即使某個 Bigram 沒有在語料中出現,它仍會得到至少 1 的計數,不再產生 0 機率。

平滑後的機率公式

若詞彙表大小為 VV,Add-one smoothing 的條件機率是:$$P(w_j \mid w_i) = \frac{C(w_i, w_j) + 1}{\sum_{w} C(w_i, w) + V}$$

分母要加上 VV,是因為該列的每一個可能下一字都加了 11

Smoothing 的作用

Add-one smoothing 並非在說每個沒有出現的字詞組合真的都出現過一次,這只是一種計算上的處理,用來避免模型把未觀察到的組合判定為絕對不可能。

可以把它想成「即使以前沒有看過,也保留一點點可能性。」,所以原本的 0 會變成很小的正機率,而經常出現的組合仍會具有較大的機率。

如何計算整個字詞序列的機率?

語言模型除了預測下一個字,也可以計算整個句子的機率,以下有個序列:w1,w2,,wnw_1,w_2,…,w_n,根據機率的連鎖律(Chain Rule),可以寫成:$$P(w_1, w_2, \ldots, w_n) = P(w_1)P(w_2 \mid w_1)P(w_3 \mid w_1, w_2) \cdots P(w_n \mid w_1, \ldots, w_{n-1})$$

公式意思:

  1. 第一個字出現的機率。
  2. 已知第一個字時,第二個字出現的機率。
  3. 已知前兩個字時,第三個字出現的機率。
  4. 依此類推。

Bigram 如何簡化句子機率?

完整 Chain Rule 需要使用全部歷史內容,但 Bigram 假設每個字只依賴前一個字,這部分就可以簡化為:$$P(w_1, w_2, \ldots, w_n) \approx P(w_1)P(w_2 \mid w_1)P(w_3 \mid w_2) \cdots P(w_n \mid w_{n-1})$$

而這個式子也能寫成:$$P(w_1, w_2, \ldots, w_n) \approx P(w_1) \prod_{k=2}^{n} P(w_k \mid w_{k-1})$$

句子機率範例

假設句子是 I want to eat lunch,Bigram 模型會計算 P(I want to eat lunch)P(\text{I want to eat lunch}),近似為:$$P(\text{I}) \times P(\text{want} \mid \text{I}) \times P(\text{to} \mid \text{want}) \times P(\text{eat} \mid \text{to}) \times P(\text{lunch} \mid \text{eat})$$

每一項都可以從 Bigram Count Matrix 中的相對頻率得到,若這些 Bigram 在語料中經常出現,整個句子的機率就會相對較高;反之,若其中某些搭配很少出現,整體機率就會較低。

一般 N-gram Language Model

Bigram 只看前一個字,而一般 N-gram 模型則看前面 N1N−1 個字,其近似概念為:$$P(w_k \mid w_1, \ldots, w_{k-1}) \approx P(w_k \mid w_{k-N+1}, \ldots, w_{k-1})$$

Bigram 只看前一個字:P(wkwk1)P(w_k \mid w_{k-1}) ;Trigram 看前兩個字:P(wkwk2,wk1)P(w_k \mid w_{k-2}, w_{k-1})

例如要預測 lunch

  • Bigram 只看 eat
  • Trigram 會看 to eat

這個模型的完整建立流程

  • 第一步:準備 Corpus,收集大量句子或文章。
  • 第二步:切割 N-gram,若使用 Bigram,就把句子切成連續兩字。
  • 第三步:統計出現次數,建立 Bigram Count Matrix C(wi,wj)C(w_i, w_j)
  • 第四步:進行 Smoothing,避免未出現的 Bigram 機率為 0。
  • 第五步:轉換為條件機率。
  • 第六步:計算下一個字的機率,根據前一個字,查詢各候選字的條件機率。
  • 第七步:計算整個句子的機率,將每一個相鄰字的條件機率相乘,例如:$$P(w_1, \ldots, w_n) \approx P(w_1) \prod_{k=2}^{n} P(w_k \mid w_{k-1})$$

Perplexity(困惑度)

Perplexity,縮寫為 PPL,中文稱為「困惑度」,是用來衡量語言模型對一段文字有多麼困惑的量化指標。

直覺上可以理解成模型越知道下一個字應該是什麼,困惑度越低;模型越無法判斷下一個字,困惑度越高。

因此,在相同資料與評估條件下 Perplexity 越低,語言模型通常預測得越好。

Perplexity 評估的是什麼?

語言模型會根據前面已經出現的文字,預測下一個字的機率。

例如模型看到「我今天中午想吃……」這一句,模型可能預測:

候選字詞機率
午餐0.70
0.15
電腦0.01
其他其餘機率

如果正確答案是「午餐」,而模型給它很高的機率,代表模型對這段語言模式相當熟悉,因此困惑度會較低。相反地,若模型對許多候選字都給予相近的機率:

候選字詞機率
午餐0.10
0.09
電腦0.08
汽車0.08
其他分散於其他字

代表模型不知道下一個字應該是什麼,預測比較猶豫,因此困惑度較高。

Perplexity 的公式

給定一段包含 NN 個字的序列 W=w1,w2,,wNW = w_1, w_2, \dots, w_N ,Perplexity 可以寫成:$$PPL(W) = P(w_1, w_2, \ldots, w_N)^{-\frac{1}{N}}$$

或寫成:$$PPL(W) = \sqrt[N]{\frac{1}{P(w_1, w_2, \ldots, w_N)}}$$

這表示困惑度與整段文字的機率成反比:

  • 序列機率越高,Perplexity 越低。
  • 序列機率越低,Perplexity 越高。

與 N-gram Language Model 的關係

前面介紹過,N-gram Language Model 會將整段序列的機率拆成多個條件機率相乘,一般形式可表示為:$$P(w_1, \ldots, w_N) = \prod_{k=1}^{N} P(w_k \mid \text{history})$$

在 N-gram 模型中,history 只保留前面的部分字詞,例如 Bigram 模型只看前一個字:$$P(w_1, \ldots, w_N) \approx P(w_1) \prod_{k=2}^{N} P(w_k \mid w_{k-1})$$

因此,Bigram 模型的 Perplexity 可寫成:$$PPL(W) = \sqrt[N]{\frac{1}{P(w_1)P(w_2 \mid w_1)P(w_3 \mid w_2) \cdots P(w_N \mid w_{N-1})}}$$

如果模型對每一個正確的下一字都給予較高機率,分母就會較大,整體 Perplexity 就會較低。

為什麼機率越高,Perplexity 越低?

假設模型對正確下一字的預測機率很高 P(wkh)=0.9P(w_k \mid h)=0.9 ,因為 Perplexity 的公式中使用機率的倒數 10.9\frac{1}{0.9} ,所以數值不會太大。

但如果正確字的機率只有 P(wkh)=0.01P(w_k \mid h)=0.01 ,其倒數為 10.01=100\frac{1}{0.01} = 100

就會使 Perplexity 明顯提高,所以若正確字機率越高則 Perplexity 越低。

Perplexity 的直覺意義

Perplexity 可以粗略理解為模型在每個位置平均覺得有多少個差不多可能的候選答案。

例如 Perplexity 接近 1,代表模型幾乎完全確定下一個字是什麼,模型可能給出 [1,0,0,,0][1,0,0,…,0],也就是正確字的機率接近 1,其他字接近 0。

或是 Perplexity 很高,代表模型對很多字都沒有明確判斷,例如它認為十個候選字都差不多可能長這樣 [0.1,0.1,0.1,,0.1][0.1,0.1,0.1,…,0.1],此時模型的困惑程度就比較高。

歌詞例子

接下來以不同歌手的歌詞說明 Perplexity。

假設使用周杰倫的歌詞訓練一個語言模型,模型會學到周杰倫歌詞常見的用字、常見的句子組合、特定的語言風格與前後模式等等。

當測試資料也是周杰倫風格的歌詞時,模型較熟悉這些 pattern,因此能較有把握預測下一個字,對於正確字的機率較高,Perplexity 也較低。

但如果輸入的是告五人的歌詞,其用詞、句型或風格可能與訓練資料不同。

模型可能沒有看過類似組合,因此會覺得猜這個字好像可以,猜另一個字似乎也可能。此時機率會分散到多個候選字,Perplexity 就會提高。

所以結論是,Perplexity 也能反映測試資料是否符合模型在訓練資料中學到的語言模式。

Perplexity 低不代表答案一定正確

Perplexity 不能完整代表語言模型的好壞。

因為 Perplexity 主要反映的是模型對正確文字序列所分配的機率,以及模型的預測是否集中。

「很有信心」不等於「一定正確」。

例如一位學生可能非常有自信地回答錯誤答案,同樣地,語言模型也可能對錯誤的預測非常有信心。

所以低 Perplexity 並不代表所有回答都正確。

Perplexity 通常需要搭配其他評估方式,一起判斷模型實際輸出的品質與正確性。

Perplexity 比較時的注意概念

Perplexity 通常是在相同條件下進行比較,例如:

  • 使用相同的測試資料。
  • 使用相同的字詞切分方式。
  • 使用相同的 vocabulary。
  • 比較處理相同任務的語言模型。

如果測試資料不同,就不能只根據 Perplexity 數字直接斷定哪個模型一定較好。

就以前面的例子而言:

  • 周杰倫歌詞模型在周杰倫歌詞上的 Perplexity 可能較低。
  • 但在其他歌手的歌詞上,Perplexity 可能較高。

這表示模型對自己的訓練領域較熟悉,不代表它在所有類型的文字上都同樣有效。

總整理

為什麼需要 LSA/LSI?

傳統搜尋通常使用字詞完全匹配(Exact Match),但自然語言存在兩個問題:

  • 有相同字詞,不代表語意相同:例如 MySQL databasegenome database 都包含 database,卻屬於不同領域。
  • 沒有相同字詞,不代表內容無關:例如文章只有 Debian,沒有 Linux,但仍與 Linux 作業系統高度相關。

因此,需要從字詞共同出現的模式中,找出文件背後的隱藏概念。

核心概念

  • 潛在語意分析(Latent Semantic Analysis, LSA)
  • 潛在語意索引(Latent Semantic Indexing, LSI)

核心假設:若兩個字經常出現在相似的文件或上下文中,它們可能具有語意關係。

LSI 是一種:

  • 統計方法(Statistical Technique)
  • 資料驅動方法(Data-driven Method)
  • 使用奇異值分解(Singular Value Decomposition, SVD)的線性代數方法

字詞-文件矩陣(Term-document Matrix)

首先建立字詞-文件矩陣(Term-document Matrix):

  • 每一列:一個字詞。
  • 每一欄:一篇文件。
  • 每個數值:字詞在文件中的出現次數。

矩陣通常非常稀疏(Sparse),因為一篇文章只會使用整個詞彙庫中的少部分字詞,大多數位置都是 0。

用 SVD 找出隱藏結構

假設原始矩陣為 XX,SVD 將其分解為:X=UΣVTX=U\Sigma V^T

  • UU:字詞與潛在結構的關係。
  • Σ\Sigma:由奇異值組成的對角矩陣。
  • VTV^T:文件與潛在結構的關係。

奇異值越大,代表該成分越重要。

只保留前 KK 個較大的奇異值:X^=UΣ^VT\hat{X}=U\hat{\Sigma}V^T

此過程稱為降維(Dimensionality Reduction),目的為:

  • 保留主要語意結構。
  • 移除較不重要或類似雜訊的資訊。
  • 將原始高維資料轉換成較低維的表示。

重建矩陣的意義

原始矩陣中的數字代表實際詞頻,重建後的矩陣數字則代表字詞與文件之間的關聯程度。

因此,數值可能:

  • 從 0 變成正數。
  • 從 1 變成小於 1。
  • 比原始值更大。
  • 出現負數。

負數不代表字詞出現負數次,只是低維向量空間中的方向或關聯表示。

LSI 能透過間接共現關係,推測未直接出現某個字詞的文件,仍可能與該字詞的概念相關。

LSI 在文件檢索中的作用

LSI 將傳統的字詞層級比對,提升為潛在概念層級的比對。

因此,即使查詢與文件沒有完全相同的字詞,只要兩者在低維語意空間中相近,仍可能被判定為相關。

LSI 的限制

  • 字詞-文件矩陣可能非常龐大。
  • 矩陣包含大量 0,十分稀疏。
  • 大型矩陣執行 SVD 的成本很高。
  • 新增字詞或文件後,整個語意空間可能需要重新計算。
  • 不適合處理規模龐大且持續變動的網路資料。

LSI 較適合:

  • 小型文件庫。
  • 封閉式資料集合。
  • 特定領域文章。
  • 文件數量相對固定的環境。

機率式語言模型與 Word2Vec

語言模型的基本概念

語言模型(Language Model)的目標是根據目前已知的內容,估計下一個字或某段字詞序列出現的機率。

語言具有前後順序,因此通常使用條件機率表示:P(下一個字先前內容)P(\text{下一個字}\mid\text{先前內容})

語言模型的概念也能用於其他序列資料,例如:

  • 機器手臂的動作順序。
  • 自駕車的感測器資料。
  • 車輛加速、煞車與轉向行為。

只要資料具有時間順序與前後依賴關係,就能使用類似方法描述。

Unigram Model

Unigram Model 假設所有字彼此獨立:P(w1,,wn)=iP(wi)P(w_1,\ldots,w_n)=\prod_iP(w_i)

缺點是完全不考慮字詞順序,因此:

  • the cat licked its fur
  • fur its licked cat the

可能得到相同機率,無法合理表示文法與語意。

Bigram Model

Bigram Model 假設目前字詞主要由前一個字決定:P(w1,,wn)=iP(wiwi1)P(w_1,\ldots,w_n)=\prod_iP(w_i\mid w_{i-1})

與 Unigram 相比,Bigram 能考慮基本字詞順序,但上下文範圍仍然很短,無法掌握距離較遠的語意關係。

Context Window

Word2Vec 使用上下文視窗(Context Window)。

若中心字位於位置 cc,視窗大小為 mm,則考慮:wcm,,wc1,wc+1,,wc+mw_{c-m},\ldots,w_{c-1},w_{c+1},\ldots,w_{c+m}

例如 cat [licked] its

  • 中心字:licked
  • 左側 Context:cat
  • 右側 Context:its

CBOW

連續詞袋模型(Continuous Bag of Words, CBOW)使用周圍的上下文預測中心字:P(wcwcm,,wc1,wc+1,,wc+m)P(w_c\mid w_{c-m},\ldots,w_{c-1},w_{c+1},\ldots,w_{c+m})

例如:

[cat,its]licked[\text{cat},\text{its}]\rightarrow\text{licked}

記憶方式:看周圍,猜中間。

Skip-gram

Skip-gram 與 CBOW 相反,使用中心字預測周圍的上下文字:P(wcm,,wc1,wc+1,,wc+mwc)P(w_{c-m},\ldots,w_{c-1},w_{c+1},\ldots,w_{c+m}\mid w_c)

例如:licked[cat,its]\text{licked}\rightarrow[\text{cat},\text{its}]

記憶方式:看中間,猜周圍。

CBOW 與 Skip-gram 比較

模型輸入預測目標
CBOW周圍的 Context中心字
Skip-gram中心字周圍的 Context

兩者都透過字詞的上下文關係學習 Word Embedding。

catdog 經常出現在相似環境中,模型就可能讓兩者的向量較接近;truck 出現在不同語境,其向量便可能較遠。

Skip-gram 的訓練方式

1. 建立訓練資料

假設語料為:The cat licked its fur. The truck moved.,設定 window = 1,每個中心字會與左右相鄰字形成獨立配對。

例如中心字為 cat

  • (cat, the)
  • (cat, licked)

即使 window = 2,每筆資料仍然只包含:

  • 一個中心字。
  • 一個正確 Context 字。

視窗越大,只是產生更多 Word Pairs。

2. 自我監督學習

每個 Word Pair 都具有明確輸入與答案,因此形式上類似監督式學習。

但答案並非人工標註,而是直接從原始文章產生,因此 Word2Vec 可視為自我監督學習(Self-supervised Learning)。

3. 神經網路結構

Skip-gram 使用只有一層隱藏層的淺層前饋神經網路:Input LayerHidden LayerOutput Layer\text{Input Layer}\rightarrow\text{Hidden Layer}\rightarrow\text{Output Layer}

主要包含兩個權重矩陣:WinRV×DW_{\text{in}}\in\mathbb{R}^{V\times D}WoutRD×VW_{\text{out}}\in\mathbb{R}^{D\times V}

其中:

  • VV:詞彙庫大小。
  • DD:Embedding 維度。

4. One-hot Vector 與 Embedding

每個輸入字先表示成長度為 VV 的 One-hot Vector。

假設 cat 位於詞彙表第 3 個位置:xcat=[0,0,1,0,,0]x_{\text{cat}}=[0,0,1,0,\ldots,0] ,接著計算:h=xWinh=xW_{\text{in}}

因為 One-hot Vector 只有一個位置為 1,所以此運算等同於從 WinW_{\text{in}} 中取出 cat 對應的那一列。

因此 h=vcath=v_{\text{cat}},此向量就是 cat 的 Word Embedding。

5. 輸出層與 Softmax

隱藏向量再經過第二個矩陣:z=hWoutz=hW_{\text{out}} ,輸出長度為 $$V$$ 的分數,再透過 Softmax 轉換成機率:

P(wjwi)=ezjk=1VezkP(w_j\mid w_i)=\frac{e^{z_j}}{\sum_{k=1}^{V}e^{z_k}}

模型希望正確 Context 字具有較高機率。

例如輸入為 cat,正確答案為 licked,模型會調整參數,使 P(lickedcat)P(\text{licked}\mid\text{cat}) 逐漸提高。

6. Cross Entropy Loss

模型使用交叉熵(Cross Entropy)衡量預測誤差:

CE(y^,y)=i=1Vyilog(y^i)CE(\hat{y},y)=-\sum_{i=1}^{V}y_i\log(\hat{y}_i)

  • 正確 Context 字的預測機率越高,Loss 越小。
  • 正確 Context 字的預測機率越低,Loss 越大。

7. 正樣本與負樣本

  • 在 Context Window 中實際共同出現的字詞配對是正樣本(Positive Data)。
  • 沒有共同出現的字詞可視為負樣本(Negative Data)。

由於詞彙表很大,負樣本數量遠多於正樣本。若全部使用,會造成:

  • 嚴重資料不平衡。
  • 計算成本過高。
  • 模型難以訓練。

因此,實際訓練通常只挑選部分負樣本。

8. 兩套 Embedding

Word2Vec 實際上包含兩套字詞向量:

  1. Input Embedding:字詞作為中心字時使用的向量 viv_i
  2. Output Embedding:字詞作為 Context 字時使用的向量 uiu_i

同一個字在兩個權重矩陣中會有不同表示。

9. Embedding 維度不是越高越好

較高維度能提高模型容量,但也會增加:

  • 參數數量。
  • 記憶體需求。
  • 訓練時間。
  • 後續向量運算成本。

維度增加並不代表效果會等比例提升,因此需要依資料量與任務需求選擇。

10. 訓練完成後保留的內容

Word2Vec 的主要目的並不是保留預測相鄰字的分類器,而是取得學習完成的詞向量矩陣:

WinRV×DW_{\text{in}}\in\mathbb{R}^{V\times D}

其中每一列就是一個字的 Embedding,可直接提供後續 NLP 任務使用。

完整流程

  1. 準備語料庫。
  2. 根據 Context Window 建立 Word Pairs。
  3. 將中心字轉成 One-hot Vector。
  4. 使用 WinW_{\text{in}} 取得中心字向量。
  5. 使用 WoutW_{\text{out}} 計算輸出分數。
  6. 經過 Softmax 轉換為機率。
  7. 使用正確 Context 計算 Loss 並更新權重。
  8. 訓練完成後取出 WinW_{\text{in}} 作為 Word Embedding。

常見的 Word Embedding 模型

1. Word2Vec

Word2Vec 透過局部上下文預測任務學習字詞向量,包括:

  • CBOW。
  • Skip-gram。

主要根據一次次中心字與 Context 字的配對進行訓練。

2. GloVe

GloVe 全名為 Global Vectors for Word Representation。

其特色是使用整個語料庫的全域共現統計資訊(Global Co-occurrence Statistics)學習詞向量。

簡單比較:

  • Word2Vec:著重局部 Context 配對。
  • GloVe:著重整體語料庫的共現統計。

GloVe 也具有可直接使用的預訓練向量(Pre-trained Vectors)。

3. FastText

FastText 不只把完整單字當成一個單位,也會分析單字內部的字元與拼字結構。

例如:

  • play
  • plays
  • played
  • playing

這些字具有相似的詞形(Morphology),FastText 能利用其內部結構學習關係。

FastText 與 OOV

OOV(Out-of-Vocabulary)代表詞彙表外單字。

傳統 Word2Vec 若沒看過某個完整單字,就無法取得其向量;FastText 則能根據字元或子字詞結構,估計未見單字的 Embedding。

因此,FastText 適合:

  • 拼字變化多的資料。
  • 詞形變化明顯的語言。
  • 經常出現新字或未知字的環境。

不同語言的差異

英文具有字首、字根、字尾、時態與單複數變化,使用字元特徵通常具有明確意義。

中文的構詞方式與英文不同,因此英文有效的字元規律,不一定能直接套用到中文。

Embedding 的效果會受到以下因素影響:

  • 語言。
  • 訓練語料。
  • 使用領域。
  • 詞彙分布。
  • 下游任務。

預訓練詞向量

Word2Vec、GloVe 與 FastText 都可能提供預訓練詞向量。

優點包括:

  • 不必自行收集大量語料。
  • 不必重新訓練。
  • 可以直接將字詞轉換成向量。
  • 能快速應用於後續 NLP 任務。

實際選擇的不是單純的演算法,而是演算法+語言+訓練語料。

模型選擇原則

  • GloVe:適合一般性任務及使用全域統計資訊。
  • FastText:適合具有拼字、詞形變化及 OOV 問題的資料。
  • 自行訓練 Word2Vec:適合特殊領域或預訓練向量無法涵蓋的詞彙。

例如:

  • 古典中文。
  • 醫學文件。
  • 特定學術領域。
  • 公司內部術語。
  • 特殊社群用語。

沒有任何模型能保證在所有任務上表現最好,應在實際資料與任務上進行比較。

評估方法

可以使用基準資料集(Benchmark Dataset),例如 WordSim353:

  • 資料集提供多組字詞配對。
  • 每組字詞具有人工相似度分數。
  • 計算模型向量的相似度。
  • 比較模型結果與人工評分是否一致。

也可以直接觀察:

  • catdog 是否較接近。
  • cattruck 是否較遠。
  • 相似概念是否形成相近向量。

Word Vector 的價值

單純的 ID 只能識別字詞,數字大小沒有語意。

One-hot Vector 雖能區分字詞,但不同字詞之間通常彼此正交,無法直接反映相似性。

Word Embedding 則是從資料中學習出的數值表示,可以用來:

  • 計算字詞相似度。
  • 比較字詞關係。
  • 作為後續模型的輸入。
  • 支援各種下游任務(Downstream Tasks)。

這裡的「理解」是指模型學到可計算的統計表示,不代表模型具有和人類完全相同的語意理解。

N-gram 與 N-gram Language Model

N-gram 的定義

N-gram 是由連續 NN 個字詞組成的序列。

Please turn your homework 為例:

  • Unigram:pleaseturnyourhomework
  • Bigram:please turnturn youryour homework
  • Trigram:please turn yourturn your homework

有時「使用到 3-gram」也可能表示同時使用:

  • 1-gram。
  • 2-gram。
  • 3-gram。

N-gram 與語言模型的差異

  • N-gram:只是文字的切割方式。
  • N-gram Language Model:統計 N-gram 在語料庫中的次數,用來估計下一個字的機率。

這是一種傳統計數式語言模型,不是神經網路模型。

Bigram Count Matrix

Bigram Language Model 統計連續兩字的次數 C(wi,wj)C(w_i,w_j),矩陣中:

  • 每一列:前一個字。
  • 每一欄:下一個字。
  • 每個格子:兩個字連續出現的次數。

使用相對頻率計算條件機率

一般公式為:

P(wh)=C(h,w)C(h)P(w\mid h)=\frac{C(h,w)}{C(h)}

其中:

  • ww:要預測的字。
  • hh:先前的歷史內容。
  • C(h,w)C(h,w):歷史內容後接 $$w$$ 的次數。
  • C(h)C(h):歷史內容出現的總次數。

Bigram 只保留前一個字:

P(wjwi)=C(wi,wj)wC(wi,w)P(w_j\mid w_i)= \frac{C(w_i,w_j)} {\sum_w C(w_i,w)}

例如:

P(wantI)=C(I want)C(I)P(\text{want}\mid\text{I})= \frac{C(\text{I want})}{C(\text{I})}

Bigram 的近似假設

完整語言模型應考慮所有前文:P(wkw1,w2,,wk1)P(w_k\mid w_1,w_2,\ldots,w_{k-1})

Bigram 將其近似成:P(wkwk1)P(w_k\mid w_{k-1})

也就是預測下一個字時,只看最接近的前一個字。

優點是計算與統計較容易;缺點是忽略長距離上下文。

零機率問題

若某個 Bigram 在語料庫中從未出現 C(wi,wj)=0C(w_i,w_j)=0,則 P(wjwi)=0P(w_j\mid w_i)=0

計算整個句子機率時,所有條件機率需要相乘。只要其中一項為 0,整個句子的機率就會變成 0。

這不代表句子絕對不可能,只代表訓練語料沒有觀察到該組合。

Add-k Smoothing

為避免零機率,可使用平滑(Smoothing)。

k=1k=1 時稱為 Add-one Smoothing:C(wi,wj)=C(wi,wj)+1C'(w_i,w_j)=C(w_i,w_j)+1

若詞彙表大小為 VV,平滑後的機率為:

P(wjwi)=C(wi,wj)+1wC(wi,w)+VP(w_j\mid w_i)= \frac{C(w_i,w_j)+1} {\sum_w C(w_i,w)+V}

分母加上 VV,是因為每個可能的下一字都增加了 1。

平滑的目的不是假裝所有組合都真正出現過,而是對未觀察過的組合保留一個很小但非零的可能性。

計算整個句子的機率

根據機率連鎖律(Chain Rule):

P(w1,,wn)=P(w1)P(w2w1)P(w3w1,w2)P(wnw1,,wn1)P(w_1,\ldots,w_n) = P(w_1) P(w_2\mid w_1) P(w_3\mid w_1,w_2) \cdots P(w_n\mid w_1,\ldots,w_{n-1})

Bigram 將其簡化為:

P(w1,,wn)P(w1)k=2nP(wkwk1)P(w_1,\ldots,w_n) \approx P(w_1)\prod_{k=2}^{n}P(w_k\mid w_{k-1})

也就是將相鄰字詞的條件機率依序相乘。

N 值與上下文範圍

  • Bigram:使用前一個字。
  • Trigram:使用前兩個字。
  • N 越大:能保留更多上下文資訊。
  • N 越大:需要的語料與統計量也越多,更容易遇到資料稀疏問題。

例如預測 lunch

  • Bigram 只看 eat
  • Trigram 會看 to eat

完整建立流程

  1. 準備語料庫(Corpus)。
  2. 將句子切割成 N-gram。
  3. 統計 N-gram 出現次數。
  4. 建立 Count Matrix。
  5. 使用 Smoothing 避免零機率。
  6. 將次數轉換成條件機率。
  7. 根據歷史內容預測下一個字。
  8. 將各條件機率相乘,計算整個句子的機率。

核心觀念比較

方法核心資料學習方式主要用途主要限制
LSI字詞-文件矩陣SVD 降維潛在語意檢索SVD 成本高、擴展性差
N-gram LMN-gram 次數統計條件機率預測下一字、句子機率上下文短、資料稀疏
Word2Vec中心字與 Context 配對神經網路預測學習 Word EmbeddingOOV、需足夠語料
GloVe全域共現矩陣全域統計學習一般詞向量表示受語料與領域影響
FastText字詞與內部字元結構子字詞特徵學習處理詞形與 OOV不同語言效果不同

整體發展方向可理解為:從統計字詞是否出現,進一步學習字詞之間的共現關係,再將文字轉換為可計算、可比較的向量表示。

Perplexity(困惑度)

  1. Perplexity,縮寫為 PPL,中文稱為困惑度。
  2. 這是一種評估語言模型能力或效能的量化指標。
  3. 給定序列 W=w1,w2,,wNW=w_1, w_2, \dots, w_N ,其 Perplexity 為 PPL(W)=P(w1,w2,,wN)1N\text{PPL}(W) = P(w_1, w_2, \dots, w_N)^{-\frac{1}{N}}
  4. 序列機率越高,Perplexity 越低。
  5. 模型對正確下一字越有信心,正確字的機率越高,Perplexity 通常越低。
  6. Perplexity 越高,表示模型越無法確定下一個字,機率分布較分散。
  7. N-gram 模型會先計算一連串條件機率,再利用這些機率計算 Perplexity。
  8. 模型在熟悉的資料 pattern 上通常具有較低的 Perplexity。
  9. 若測試資料與訓練資料的語言模式不同,Perplexity 通常會提高。
  10. Perplexity 越低通常代表語言模型越好,但它主要反映模型的預測信心與機率表現。
  11. 模型有信心不代表答案一定正確,因此仍需搭配其他評估方式。