一、什麼是 Latent Dirichlet Allocation
Latent Dirichlet Allocation (LDA) 是一種用於文本主題建模的概率圖模型。它假設每個文檔是從多個主題中隨機生成的,每個主題又由多個單片語成。但是,實際給定的文檔,主題和單詞都是不知道的,這些變數是潛在變數。LDA 通過訓練可以推斷出每個文檔的主題分布和每個主題內單詞分布。
LDA 的模型可以用一個圖來表示,如下所示:
digraph { rankdir=LR; subgraph cluster1 { node [style=filled,color=white]; W1 W2 W3 W4; label = "Words"; fontsize = 16; } subgraph cluster2 { node [style=filled,color=white]; T1 T2 T3 T4; label = "Topics"; fontsize = 16; } subgraph cluster3 { node [style=filled,color=white]; D1 D2 D3; label = "Documents"; fontsize = 16; } subgraph cluster4 { node [style=filled,color=lightgrey]; Z11 Z12 Z13 Z14 Z15; label = "Topic Assignments"; fontsize = 12; } subgraph cluster5 { node [style=filled,color=lightgrey]; Z21 Z22 Z23 Z24 Z25; label = "Topic Assignments"; fontsize = 12; } subgraph cluster6 { node [style=filled,color=lightgrey]; Z31 Z32 Z33 Z34 Z35; label = "Topic Assignments"; fontsize = 12; } D1 -> Z11 -> {T1 T3}; D1 -> Z12 -> {T2 T4}; D2 -> Z21 -> {T1 T3}; D2 -> Z22 -> {T2 T4}; D3 -> Z31 -> {T1 T2}; D3 -> Z32 -> {T2 T3}; D3 -> Z33 -> {T3}; D3 -> Z34 -> {T3 T4}; D3 -> Z35 -> {T4}; {T1 T2 T3 T4} -> W1; {T1 T2 T3 T4} -> W2; {T1 T2 T3 T4} -> W3; {T1 T2 T3 T4} -> W4; }
這張圖中,表示一篇文檔 $D_i$ 是由一個主題集合 $\{T_1, T_2, …, T_k\}$ 中各個主題按一定概率組合而成的。每個主題 $T_i$ 都是一個單詞集合 $\{w_1, w_2, …, w_n\}$,生成主題的過程類似於文檔到主題的過程,即每個單詞 $w_j$ 按一定概率被分配到某個主題 $T_i$ 上。
二、LDA 模型的數學推導
為了更好地理解 LDA,我們需要了解一下 Dirichlet 分布,它是 LDA 模型中的一個關鍵概率分布。
2.1 Dirichlet 分布
Dirichlet 分布是一種多元隨機變數分布,它的一維形式是 Beta 分布。Dirichlet 分布是一個 $K$ 維概率分布向量 $\boldsymbol{\theta}=\{\theta_1, \theta_2, …, \theta_K\}$ 的概率密度函數,公式如下:
$$
p(\boldsymbol{\theta}|\boldsymbol{\alpha})=\frac{1}{B(\boldsymbol{\alpha})}\prod_{k=1}^{K}\theta_k^{\alpha_k-1}
$$
其中 $\boldsymbol{\alpha}$ 是一個 $K$ 維向量,稱為 Dirichlet 分布的超參數,它控制了分布的形態。
對於一個概率分布 $\boldsymbol{\theta}$,如果 $\alpha_1=\alpha_2=…=\alpha_K=1$,則稱這個分布是均勻分布。
那麼 Dirichlet 分布有什麼應用呢?在 LDA 模型中,每個主題的單詞分布和每個文檔的主題分布都可以看作是一個 Dirichlet 分布的實現。
2.2 Gibbs Sampling
Gibbs Sampling 是一種基於馬爾科夫鏈 Monte Carlo 方法,用於從複雜分布中採樣的技術。在 LDA 模型中,我們使用 Gibbs Sampling 演算法從後驗概率分布中採樣文檔的主題分布和主題的單詞分布。
Gibbs Sampling 演算法有以下幾個步驟:
- 隨機選擇一個文檔 $D_i$ 和一個詞 $w_{ij}$;
- 從 $D_i$ 中移除 $w_{ij}$;
- 通過後驗概率計算 $w_{ij}$ 屬於每個主題的概率,即 $p(z_{ij}=k|z_{-ij},w)$;
- 根據上一步計算出的概率,採樣一個新的主題 $k_{new}$;
- 將 $w_{ij}$ 分配到 $k_{new}$ 中;
- 重複上述步驟多次,採樣到的文檔的主題分布和主題的單詞分布就是後驗概率分布中的一個樣本。
2.3 LDA 模型的推導
了解了 Dirichlet 分布和 Gibbs Sampling 演算法之後,來看一下 LDA 模型的數學推導。
我們假設有 $K$ 個主題,每個主題由一個概率向量 $\boldsymbol{\phi_k}$ 表示,其中第 $j$ 個元素 $\phi_{kj}$ 表示主題 $k$ 中單詞 $j$ 的概率。
每個文檔 $D_i$ 由一個主題分布向量 $\boldsymbol{\theta_i}$ 表示,其中第 $k$ 個元素 $\theta_{ik}$ 表示文檔 $D_i$ 中主題 $k$ 出現的概率。
在給定主題 $\boldsymbol{\phi_k}$ 和文檔主題分布 $\boldsymbol{\theta_i}$ 的情況下,單詞 $w_{ij}$ 屬於主題 $k$ 的概率可以通過以下公式計算:
$$
p(z_{ij}=k|w_{ij},\boldsymbol{\phi_k},\boldsymbol{\theta_i})=\frac{\phi_{kw_{ij}}\theta_{ik}}{\sum_{l=1}^{K}\phi_{lw_{ij}}\theta_{il}}
$$
其中,$z_{ij}$ 表示單詞 $w_{ij}$ 的主題分配,即 $z_{ij}=k$ 表示 $w_{ij}$ 屬於主題 $k$。
對於給定的文檔集 $\boldsymbol{D}$,我們希望求得主題分布 $\boldsymbol{\theta}$ 和主題的單詞分布 $\boldsymbol{\phi}$,使得每篇文檔 $\boldsymbol{d_i}$ 的單詞序列 $\boldsymbol{w_i}$(其中每個單詞 $w_{ij}$ 屬於某個主題 $z_{ij}$)的生成概率最高:
$$
p(\boldsymbol{D}|\boldsymbol{\alpha},\boldsymbol{\beta})=\prod_{i=1}^{M}p(\boldsymbol{d_i}|\boldsymbol{\alpha},\boldsymbol{\beta})=\prod_{i=1}^{M}\int_{\boldsymbol{\theta}}\sum_{\boldsymbol{z}}p(\boldsymbol{d_i}|\boldsymbol{\theta},\boldsymbol{\beta})p(\boldsymbol{\theta}|\boldsymbol{\alpha})p(\boldsymbol{z}|\boldsymbol{\theta})d\boldsymbol{\theta}
$$
其中 $\boldsymbol{\alpha}$ 和 $\boldsymbol{\beta}$ 都是 Dirichlet 分布的超參數。
對於某個文檔 $\boldsymbol{d_i}$,我們可以使用 Gibbs Sampling 迭代得到 $T$ 個樣本 $\{\boldsymbol{\theta_i^{(t)}},\boldsymbol{z_i^{(t)}}\}$。在得到所有文檔的 $T$ 個樣本之後,我們可以針對每個單詞 $w_{ij}$,計算它所屬主題的分布 $p(z_{ij}=k|\boldsymbol{D})$,這個分布即為 LDA 模型的推斷結果。
三、LDA 實現
3.1 數據預處理
在實現 LDA 之前,我們需要對文本數據進行預處理,包括分詞、去停用詞、詞幹提取等。這裡我們以新聞數據集為例,通過 Python 中的 NLTK 庫進行文本預處理。
import nltk from nltk.tokenize import word_tokenize from nltk.corpus import stopwords from nltk.stem.porter import PorterStemmer nltk.download('stopwords') nltk.download('punkt') def preprocess(text): tokens = word_tokenize(text) stop_words = set(stopwords.words('english')) tokens = [w for w in tokens if not w.lower() in stop_words] stemmer = PorterStemmer() tokens = [stemmer.stem(w) for w in tokens] return tokens # 讀取文件 with open('news.txt', 'r') as f: raw_text = f.read() # 預處理文本 tokens = preprocess(raw_text)
3.2 構建詞典
在 LDA 中,我們需要構建一個詞典,將詞語映射為整數。這個詞典的大小決定了單詞分布的維度。我們可以在文本預處理的過程中,統計每個單詞出現的次數,然後通過給每個單詞分配一個唯一的整數來構建詞典。
# 構建詞典 vocab = {} for word in tokens: if word not in vocab: vocab[word] = len(vocab)
3.3 計算單詞分布
在 LDA 中,單詞的分布與主題的分布同等重要。我們需要計算每個主題中每個單詞的概率分布。這裡我們仍然使用詞頻作為單詞分布的度量,即對於主題 $k$ 中的單詞 $w_j$,其概率為:
$$
\phi_{kj}=\frac{n_{kj}}{\sum_{j=1}^{W}n_{kj}}
$$
其中,$n_{kj}$ 表示主題 $k$ 中單詞 $w_j$ 出現的次數,而分母則是主題 $k$ 中的總單詞數。
import numpy as np # 初始化單詞分布 K = 10 # 主題數 W = len(vocab) # 辭彙量 beta = np.ones((K, W)) # 每個主題的單詞分布 for k in range(K): for w in range(W): beta[k, w] += np.sum(n[k, vocab_inv[w], :]) beta[k, :] /= np.sum(beta[k, :])
3.4 計算文檔主題分布
在 LDA 中,我們還需要計算每篇文檔的主題分布。這可以通過 Gibbs Sampling 演算法得到。我們初始化文檔主題分布為一個均勻分布,然後迭代多次,使得文檔
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/288693.html