一文讀懂如何用LSA、PSLA、LDA和lda2vec進行主題建模

一文讀懂如何用LSA、PSLA、LDA和lda2vec進行主題建模

來自專欄機器之心89 人贊了文章

選自 Medium,作者:Joyce X,機器之心編譯。

本文是一篇關於主題建模及其相關技術的綜述。文中介紹了四種最流行的技術,用於探討主題建模,它們分別是:LSA、pLSA、LDA,以及最新的、基於深度學習的 lda2vec。

在自然語言理解任務中,我們可以通過一系列的層次來提取含義——從單詞、句子、段落,再到文檔。在文檔層面,理解文本最有效的方式之一就是分析其主題。在文檔集合中學習、識別和提取這些主題的過程被稱為主題建模。

在本文中,我們將通過 4 種最流行的技術來探討主題建模,它們分別是:LSA、pLSA、LDA,以及最新的、基於深度學習的 lda2vec。

概述

所有主題模型都基於相同的基本假設:

  • 每個文檔包含多個主題;
  • 每個主題包含多個單詞。

換句話說,主題模型圍繞著以下觀點構建:實際上,文檔的語義由一些我們所忽視的隱變數或「潛」變數管理。因此,主題建模的目標就是揭示這些潛在變數——也就是主題,正是它們塑造了我們文檔和語料庫的含義。這篇博文將繼續深入不同種類的主題模型,試圖建立起讀者對不同主題模型如何揭示這些潛在主題的認知。

LSA

潛在語義分析(LSA)是主題建模的基礎技術之一。其核心思想是把我們所擁有的文檔-術語矩陣分解成相互獨立的文檔-主題矩陣和主題-術語矩陣。

第一步是生成文檔-術語矩陣。如果在辭彙表中給出 m 個文檔和 n 個單詞,我們可以構造一個 m×n 的矩陣 A,其中每行代表一個文檔,每列代表一個單詞。在 LSA 的最簡單版本中,每一個條目可以簡單地是第 j 個單詞在第 i 個文檔中出現次數的原始計數。然而,在實際操作中,原始計數的效果不是很好,因為它們無法考慮文檔中每個詞的權重。例如,比起「test」來說,「nuclear」這個單詞也許更能指出給定文章的主題。

因此,LSA 模型通常用 tf-idf 得分代替文檔-術語矩陣中的原始計數。tf-idf,即詞頻-逆文本頻率指數,為文檔 i 中的術語 j 分配了相應的權重,如下所示:

直觀地說,術語出現在文檔中的頻率越高,則其權重越大;同時,術語在語料庫中出現的頻率越低,其權重越大。

一旦擁有文檔-術語矩陣 A,我們就可以開始思考潛在主題。問題在於:A 極有可能非常稀疏、雜訊很大,並且在很多維度上非常冗餘。因此,為了找出能夠捕捉單詞和文檔關係的少數潛在主題,我們希望能降低矩陣 A 的維度。

這種降維可以使用截斷 SVD 來執行。SVD,即奇異值分解,是線性代數中的一種技術。該技術將任意矩陣 M 分解為三個獨立矩陣的乘積:M=U*S*V,其中 S 是矩陣 M 奇異值的對角矩陣。很大程度上,截斷 SVD 的降維方式是:選擇奇異值中最大的 t 個數,且只保留矩陣 U 和 V 的前 t 列。在這種情況下,t 是一個超參數,我們可以根據想要查找的主題數量進行選擇和調整。

直觀來說,截斷 SVD 可以看作只保留我們變換空間中最重要的 t 維。

在這種情況下,U∈?^(m?t)是我們的文檔-主題矩陣,而 V∈?^(n?t)則成為我們的術語-主題矩陣。在矩陣 U 和 V 中,每一列對應於我們 t 個主題當中的一個。在 U 中,行表示按主題表達的文檔向量;在 V 中,行代表按主題表達的術語向量。

通過這些文檔向量和術語向量,現在我們可以輕鬆應用餘弦相似度等度量來評估以下指標:

  • 不同文檔的相似度
  • 不同單詞的相似度
  • 術語(或「queries」)與文檔的相似度(當我們想要檢索與查詢最相關的段落,即進行信息檢索時,這一點將非常有用)

代碼實現

在 sklearn 中,LSA 的簡單實現可能如下所示:

from sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.decomposition import TruncatedSVDfrom sklearn.pipeline import Pipelinedocuments = ["doc1.txt", "doc2.txt", "doc3.txt"] # raw documents to tf-idf matrix: vectorizer = TfidfVectorizer(stop_words=english, use_idf=True, smooth_idf=True)# SVD to reduce dimensionality: svd_model = TruncatedSVD(n_components=100, // num dimensions algorithm=randomized, n_iter=10)# pipeline of tf-idf + SVD, fit to and applied to documents:svd_transformer = Pipeline([(tfidf, vectorizer), (svd, svd_model)])svd_matrix = svd_transformer.fit_transform(documents)# svd_matrix can later be used to compare documents, compare words, or compare queries with documents

LSA 方法快速且高效,但它也有一些主要缺點:

  • 缺乏可解釋的嵌入(我們並不知道主題是什麼,其成分可能積極或消極,這一點是隨機的)
  • 需要大量的文件和辭彙來獲得準確的結果
  • 表徵效率低

PLSA

pLSA,即概率潛在語義分析,採取概率方法替代 SVD 以解決問題。其核心思想是找到一個潛在主題的概率模型,該模型可以生成我們在文檔-術語矩陣中觀察到的數據。特別是,我們需要一個模型 P(D,W),使得對於任何文檔 d 和單詞 w,P(d,w) 能對應於文檔-術語矩陣中的那個條目。

讓我們回想主題模型的基本假設:每個文檔由多個主題組成,每個主題由多個單片語成。pLSA 為這些假設增加了概率自旋:

  • 給定文檔 d,主題 z 以 P(z|d) 的概率出現在該文檔中
  • 給定主題 z,單詞 w 以 P(w|z) 的概率從主題 z 中提取出來

從形式上看,一個給定的文檔和單詞同時出現的聯合概率是:

直觀來說,等式右邊告訴我們理解某個文檔的可能性有多大;然後,根據該文檔主題的分布情況,在該文檔中找到某個單詞的可能性有多大。

在這種情況下,P(D)、P(Z|D)、和 P(W|Z) 是我們模型的參數。P(D) 可以直接由我們的語料庫確定。P(Z|D) 和 P(W|Z) 利用了多項式分布建模,並且可以使用期望最大化演算法(EM)進行訓練。EM 無需進行演算法的完整數學處理,而是一種基於未觀測潛變數(此處指主題)的模型找到最可能的參數估值的方法。

有趣的是,P(D,W) 可以利用不同的的 3 個參數等效地參數化:

可以通過將模型看作一個生成過程來理解這種等價性。在第一個參數化過程中,我們從概率為 P(d) 的文檔開始,然後用 P(z|d) 生成主題,最後用 P(w|z) 生成單詞。而在上述這個參數化過程中,我們從 P(z) 開始,再用 P(d|z) 和 P(w|z) 單獨生成文檔。

這個新參數化方法非常有趣,因為我們可以發現 pLSA 模型和 LSA 模型之間存在一個直接的平行對應關係:

其中,主題 P(Z) 的概率對應於奇異主題概率的對角矩陣,給定主題 P(D|Z) 的文檔概率對應於文檔-主題矩陣 U,給定主題 P(W|Z) 的單詞概率對應於術語-主題矩陣 V。

那麼,這說明了什麼?儘管 pLSA 看起來與 LSA 差異很大、且處理問題的方法完全不同,但實際上 pLSA 只是在 LSA 的基礎上添加了對主題和辭彙的概率處理罷了。pLSA 是一個更加靈活的模型,但仍然存在一些問題,尤其表現為:

  • 因為我們沒有參數來給 P(D) 建模,所以不知道如何為新文檔分配概率
  • pLSA 的參數數量隨著我們擁有的文檔數線性增長,因此容易出現過度擬合問題

我們將不會考慮任何 pLSA 的代碼,因為很少會單獨使用 pLSA。一般來說,當人們在尋找超出 LSA 基準性能的主題模型時,他們會轉而使用 LDA 模型。LDA 是最常見的主題模型,它在 pLSA 的基礎上進行了擴展,從而解決這些問題。

LDA

LDA 即潛在狄利克雷分布,是 pLSA 的貝葉斯版本。它使用狄利克雷先驗來處理文檔-主題和單詞-主題分布,從而有助於更好地泛化。

我不打算深入講解狄利克雷分布,不過,我們可以對其做一個簡短的概述:即,將狄利克雷視為「分布的分布」。本質上,它回答了這樣一個問題:「給定某種分布,我看到的實際概率分布可能是什麼樣子?」

考慮比較主題混合概率分布的相關例子。假設我們正在查看的語料庫有著來自 3 個完全不同主題領域的文檔。如果我們想對其進行建模,我們想要的分布類型將有著這樣的特徵:它在其中一個主題上有著極高的權重,而在其他的主題上權重不大。如果我們有 3 個主題,那麼我們看到的一些具體概率分布可能會是:

  • 混合 X:90% 主題 A,5% 主題 B,5% 主題 C
  • 混合 Y:5% 主題 A,90% 主題 B,5% 主題 C
  • 混合 Z:5% 主題 A,5% 主題 B,90% 主題 C

如果從這個狄利克雷分布中繪製一個隨機概率分布,並對單個主題上的較大權重進行參數化,我們可能會得到一個與混合 X、Y 或 Z 非常相似的分布。我們不太可能會抽樣得到這樣一個分布:33%的主題 A,33%的主題 B 和 33%的主題 C。

本質上,這就是狄利克雷分布所提供的:一種特定類型的抽樣概率分布法。我們可以回顧一下 pLSA 的模型:

在 pLSA 中,我們對文檔進行抽樣,然後根據該文檔抽樣主題,再根據該主題抽樣一個單詞。以下是 LDA 的模型:

根據狄利克雷分布 Dir(α),我們繪製一個隨機樣本來表示特定文檔的主題分布或主題混合。這個主題分布記為θ。我們可以基於分布從θ選擇一個特定的主題 Z。

接下來,從另一個狄利克雷分布 Dir(??),我們選擇一個隨機樣本來表示主題 Z 的單詞分布。這個單詞分布記為φ。從φ中,我們選擇單詞 w。

從形式上看,從文檔生成每個單詞的過程如下(注意,該演算法使用 c 而不是 z 來表示主題):

通常而言,LDA 比 pLSA 效果更好,因為它可以輕而易舉地泛化到新文檔中去。在 pLSA 中,文檔概率是數據集中的一個固定點。如果沒有看到那個文件,我們就沒有那個數據點。然而,在 LDA 中,數據集作為訓練數據用於文檔-主題分布的狄利克雷分布。即使沒有看到某個文件,我們可以很容易地從狄利克雷分布中抽樣得來,並繼續接下來的操作。

代碼實現

LDA 無疑是最受歡迎(且通常來說是最有效的)主題建模技術。它在 gensim 當中可以方便地使用:

from gensim.corpora.Dictionary import load_from_text, doc2bowfrom gensim.corpora import MmCorpusfrom gensim.models.ldamodel import LdaModeldocument = "This is some document..."# load id->word mapping (the dictionary)id2word = load_from_text(wiki_en_wordids.txt)# load corpus iteratormm = MmCorpus(wiki_en_tfidf.mm)# extract 100 LDA topics, updating once every 10,000lda = LdaModel(corpus=mm, id2word=id2word, num_topics=100, update_every=1, chunksize=10000, passes=1)# use LDA model: transform new doc to bag-of-words, then apply ldadoc_bow = doc2bow(document.split())doc_lda = lda[doc_bow]# doc_lda is vector of length num_topics representing weighted presence of each topic in the doc

通過使用 LDA,我們可以從文檔語料庫中提取人類可解釋的主題,其中每個主題都以與之關聯度最高的詞語作為特徵。例如,主題 2 可以用諸如「石油、天然氣、鑽井、管道、楔石、能量」等術語來表示。此外,在給定一個新文檔的條件下,我們可以獲得表示其主題混合的向量,例如,5% 的主題 1,70% 的主題 2,10%的主題 3 等。通常來說,這些向量對下游應用非常有用。

深度學習中的 LDA:lda2vec

那麼,這些主題模型會將哪些因素納入更複雜的自然語言處理問題中呢?

在文章的開頭,我們談到能夠從每個級別的文本(單詞、段落、文檔)中提取其含義是多麼重要。在文檔層面,我們現在知道如何將文本表示為主題的混合。在單詞級別上,我們通常使用諸如 word2vec 之類的東西來獲取其向量表徵。lda2vec 是 word2vec 和 LDA 的擴展,它共同學習單詞、文檔和主題向量。

以下是其工作原理。

lda2vec 專門在 word2vec 的 skip-gram 模型基礎上建模,以生成單詞向量。skip-gram 和 word2vec 本質上就是一個神經網路,通過利用輸入單詞預測周圍上下文詞語的方法來學習詞嵌入。

通過使用 lda2vec,我們不直接用單詞向量來預測上下文單詞,而是使用上下文向量來進行預測。該上下文向量被創建為兩個其它向量的總和:單詞向量和文檔向量。

單詞向量由前面討論過的 skip-gram word2vec 模型生成。而文檔向量更有趣,它實際上是下列兩個組件的加權組合:

  • 文檔權重向量,表示文檔中每個主題的「權重」(稍後將轉換為百分比)
  • 主題矩陣,表示每個主題及其相應向量嵌入

文檔向量和單詞向量協同起來,為文檔中的每個單詞生成「上下文」向量。lda2vec 的強大之處在於,它不僅能學習單詞的詞嵌入(和上下文向量嵌入),還同時學習主題表徵和文檔表徵。

  • 博客地址:multithreaded.stitchfix.com
  • 代碼地址:github.com/cemoody/lda2

總結

我們常把主題模型當作「有點用處」的黑箱演算法。幸運的是,與許多神經網路演算法不同,主題模型實際上是可解釋的,它可以更直接地進行診斷、調整和評估。希望這篇博文能夠解釋基礎數學知識、內在驅動力和你所需要的直覺。

原文鏈接:medium.com/nanonets/top

推薦閱讀:

「Python」用Cosine Similarity實現相關文章推薦
第十一期 | 數據科學競賽經驗分享專題篇(含講解及代碼)
Python抓取網頁數據的終極辦法
介紹一位可能過時的咖狗神器XGBoost
【3-2】GAFATA 股票數據分析

TAG:機器學習 | 數據挖掘 | 人工智慧 |