使用LSA,PLSA,LDA和lda2Vec進行建模

Source: Deep Learning on Medium


Go to the profile of Frederick Lee

覺得不錯,所以分享翻譯過後文章,原文在此

這篇文章是一個全面的概述主題建模及其相關技術。

在自然語言理解(NLU)任務中,有一個深度層次結構,通過它我們可以提取意義 — 從單詞到句子,從段落到文檔。在文檔層面,理解文本最有用的方法之一是分析其主題。在一組文檔中學習,識別和提取這些主題的過程稱為主題建模(topic modeling)。

在這篇文章中,我們將通過今天最流行的4種技術探索主題建模:LSA,pLSA,LDA和更新的,基於深度學習的lda2vec。

概觀

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

  • 每個文件都包含各種主題,以及
  • 每個主題都包含一系列單詞

換句話說,主題模型是圍繞我們的文檔的語義實際上由一些我們沒有觀察到的隱藏或“潛在”變量來管理的想法構建的。因此,主題建模的目標是揭示這些潛在變量 — 主題 — 塑造我們的文檔和語料庫的含義。本博文的其餘部分將建立對不同主題模型如何揭示這些潛在主題的理解。

LSA

潛在語義分析 Latent Semantic Analysis(LSA)是主題建模的基礎技術之一。核心思想是採用我們所擁有的矩陣 — 文檔和術語 — 並將其分解為單獨的文檔 — 主題矩陣和主題 — 術語矩陣。

第一步是生成我們的文檔術語矩陣。給定m個文檔和我們詞彙表中的n個單詞,我們可以構造一個m × n矩陣A,其中每行代表一個文檔,每列代表一個單詞。在最簡單的LSA版本中,每個條目可以簡單地是第j個單詞出現在第i個文檔中的次數的原始計數。然而,在實踐中,原始計數不能很好地起作用,因為它們沒有考慮到文檔中每個單詞的重要性。例如,“核”這個詞可能會告訴我們更多關於給定文檔的主題而不是單詞“test”。

因此,LSA模型通常用tf-idf分數替換文檔術語矩陣中的原始計數。Tf-idf或術語頻率 — 逆文檔頻率,為文檔i中的術語j分配權重,如下所示:

直觀地說,當一個術語在整個文檔中頻繁出現但在語料庫中不經常出現時,該術語具有很大的權重。單詞“build”可能經常出現在文檔中,但由於它在語料庫的其餘部分中可能相當常見,因此它的tf-idf分數不會很高。但是,如果單詞“gentrification”經常出現在文檔中,因為它在語料庫的其餘部分中更少見,它將具有更高的tf-idf分數。

一旦我們有了文檔術語矩陣A,我們就可以開始考慮我們的潛在主題了。事情就是這樣:A很可能是非常稀疏,非常嘈雜,並且在很多方面都非常冗餘。因此,為了找到捕捉單詞和文檔之間關係的少數潛在主題,我們希望在A上執行降維。

可以使用截斷的SVD(truncated SVD)來執行該降維。SVD或奇異值分解是線性代數中的一種技術,其將任何矩陣M分解為3個單獨矩陣的乘積:M = U * S * V,其中SM奇異值的對角矩陣。重要的是,truncated SVD通過僅選擇t個最大奇異值來減少維數,並且僅保留UV的前t列。在這種情況下,t是一個超參數,我們可以選擇和調整以反映我們想要查找的主題的數量。

直覺上,認為這是只保留 t在我們的變換空間中最顯著的尺寸。

在這種情況下, U ∈ ℝ^(m ⨉ t)出現作為我們的文檔主題矩陣,和 V ∈ ℝ^(n ⨉ t)變成我們的術語話題矩陣。在這兩個 UV,列對應於我們的一 t topics的連線話題。在U中,行表示以主題表示的文檔向量; 在 V中,行表示以主題表示的術語向量。

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

  • 不同文件的相似性
  • 不同詞語的相似性
  • 詞語(或“查詢”)和文檔(當我們想要檢索與我們的搜索查詢最相關的段落時,在信息檢索中變得有用)的相似性。

Code

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

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import TruncatedSVD
from sklearn.pipeline import Pipeline
documents = ["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或概率潛在語義分析 Probabilistic Latent Semantic Analysis使用概率方法而不是SVD來解決問題。核心思想是找到一個潛在主題的概率模型,可以生成我們在文檔術語矩陣中觀察到的數據。特別是,我們想要模型 P(D,W),使得對於任何文檔d和單詞w, P(d,w)對應於文檔項矩陣中的該條目。

回想一下主題模型的基本假設:每個文檔由多個主題組成,每個主題由一組單詞組成。pLSA為這些假設增加了概率旋轉:

  • 給定文檔d,主題z以概率 P(z|d)存在於該文檔中
  • 在給定主題z的情況下,從z以概率 P(w|z)繪製單詞w

在形式上,一起查看給定document和word的聯合概率是:

直覺上,這個等式的右邊告訴我們看到某個文檔的可能性有多大,然後根據該文檔的主題分佈,在該文檔中找到某個單詞的可能性有多大

在這種情況下,P(D),P(Z | D)和P(W | Z)是我們模型的參數。P(D)可以直接從我們的語料庫中確定。P(Z | D)和P(W | Z)被建模為多項分佈,並且可以使用期望最大化算法(EM) expectation-maximization algorithm 來訓練。在不對算法進行完整數學處理的情況下,EM是一種為模型找到最可能的參數估計的方法,該模型依賴於未觀察到的潛在變量(在我們的例子中是主題)。

有趣的是,P(D,W)可以使​​用一組不同的3個參數進行等效參數化:

通過將模型視為生成過程,我們可以理解這種等效性。在我們的第一個參數化中,我們從文檔開始用P(d),然後用P(z | d)生成主題,然後用P(w | z)生成單詞。在這個參數化中,我們從P(z)的主題開始,然後用P(d | z)和帶有P(w | z)的單詞獨立地生成文檔。

https://www.slideshare.net/NYCPredictiveAnalytics/introduction-to-probabilistic-latent-semantic-analysis

這個新參數化如此有趣的原因是因為我們可以看到我們的LSA模型的pLSA模型之間的直接並行:

在我們的主題P(Z)的概率對應於我們的奇異主題概率的對角矩陣的情況下,給出主題P(D | Z)的文檔的概率對應於我們的文檔 — 主題矩陣U,以及我們的單詞的概率給定的主題P(W | Z)對應於我們的長期話題矩陣V

那告訴我們什麼呢?儘管看起來非常不同並且以一種非常不同的方式解決問題,但pLSA實際上只是在LSA之上添加了對主題和單詞的概率處理。這是一個更靈活的模型,但仍然存在一些問題。特別是:

  • 因為我們沒有模型P(D)的參數,所以我們不知道如何將概率分配給新文檔
  • pLSA的參數數量與我們擁有的文檔數量呈線性增長,因此容易過度擬合

我們不會查看pLSA的任何代碼,因為它很少單獨使用。一般來說,當人們在尋找超出LSA給出的基線性能的主題模型時,他們會轉向LDA。LDA是最常見的主題模型,它擴展了PLSA以解決這些問題。

LDA

LDA代表Latent Dirichlet Allocation。LDA是pLSA的貝葉斯版本。特別是,它使用dirichlet priors進行文檔主題和單詞主題分發,從而更好地推廣。

我不打算對dirichlet發行版進行深入的處理,因為這里這裡有非常好的直觀解釋。然而,作為一個簡短的概述,我們可以將dirichlet視為“分佈上的分佈”。實質上,它回答了這個問題:“鑑於這種類型的分佈,我可能會看到一些實際的概率分佈?”

考慮比較主題混合的概率分佈的非常相關的示例。假設我們正在查看的語料庫包含來自3個截然不同的主題領域的文檔。如果我們想要對此進行建模,那麼我們想要的分佈類型將是一個非常重視一個特定主題的分佈類型,並且根本不會對其餘主題給予太多權重。如果我們有3個主題,那麼我們可能會看到的一些特定概率分佈是:

  • Mixture X:90%主題A,5%主題B,5%主題C.
  • Mixture Y:5%主題A,90%主題B,5%主題C.
  • Mixture Z:5%主題A,5%主題B,90%主題C.

如果我們從這個dirichlet分佈中繪製隨機概率分佈,通過單個主題的大權重參數化,我們可能得到一個非常類似於混合物X,混合物Y或混合物Z的分佈。我們不太可能採樣分佈為33%的主題A,33%的主題B和33%的主題C.

這基本上是dirichlet分佈提供的:一種對特定類型的概率分佈進行抽樣的方法。回想一下pLSA的模型:

在pLSA中,我們對文檔進行採樣,然後對基於該文檔的主題進行採樣,然後對基於該主題的單詞進行採樣。這是LDA的模型:

從dirichlet分佈Dir(α),我們繪製一個隨機樣本,代表特定文檔的主題分佈或主題混合。該主題分佈是θ。從θ開始,我們根據分佈選擇特定的主題Z.

接下來,從另一個dirichlet分佈Dir(β),我們選擇表示主題Z 的單詞分佈的隨機樣本。該單詞分佈是φ。從φ,我們選擇單詞w。

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

https://cs.stanford.edu/~ppasupat/a9online/1140.html

LDA通常比pLSA更好,因為它可以輕鬆地推廣到新文檔。在pLSA中,文檔概率是數據集中的固定點。如果我們沒有看到文檔,我們就沒有這個數據點。在LDA中,數據集用作文檔主題分佈的dirichlet分佈的訓練數據。如果我們沒有看到文檔,我們可以輕鬆地從dirichlet分佈中進行採樣並從那裡向前移動。

Code

LDA很容易成為最受歡迎(通常是最有效)的主題建模技術。它有gensim可供使用方便:

from gensim.corpora.Dictionary import load_from_text, doc2bow
from gensim.corpora import MmCorpus
from gensim.models.ldamodel import LdaModel
document = "This is some document..."
# load id->word mapping (the dictionary)
id2word = load_from_text('wiki_en_wordids.txt')
# load corpus iterator
mm = MmCorpus('wiki_en_tfidf.mm')
# extract 100 LDA topics, updating once every 10,000
lda = 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 lda
doc_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可以通過諸如“石油,天然氣,鑽井,管道,Keystone,能源”等術語來表徵。此外,給定新文檔,我們可以獲得表示其主題混合的向量,例如5%主題1 ,70%主題2,10%主題3等。這些向量通常對下游應用程序非常有用。

深度學習中的LDA:lda2vec

那麼這些主題模型在哪些因素中涉及更複雜的自然語言處理問題呢?

在這篇文章的開頭,我們討論了能夠從每個級別的文本中提取含義的重要性 — 單詞,段落,文檔。在文檔層面,我們現在知道如何將文本表示為主題的混合。在單詞級別,我們通常使用像word2vec這樣的東西來獲得向量表示。lda2vec是word2vec和LDA的擴展,它共同學習單詞,文檔和主題向量

這是它的工作原理。

lda2vec專門構建在word2vec的skip-gram模型之上,以生成單詞向量。如果你不熟悉skip-gram和word2vec,你可以在這裡閱讀它,但實質上它是一個通過嘗試使用輸入詞來預測周圍環境詞來學習單詞嵌入的神經網絡。

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

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

  • the document weight vector文檔權重向量,代表“權重”(後來被轉換成百分比)文檔中的每個主題的
  • the topic matrix主題矩陣,代表每個主題和其相對應的向量嵌入

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

https://multithreaded.stitchfix.com/blog/2016/05/27/lda2vec

有關該模型的更詳細概述,請查看Chris Moody的原始博文(Moody於2016年創建了lda2vec)。代碼可以在Moody的github存儲庫和這個Jupyter Notebook示例中找到。

結論

我們經常將主題模型視為“正常工作”的黑盒算法。幸運的是,與許多神經網絡不同,主題模型實際上是可以解釋的,而且更容易診斷,調整和評估。希望這篇博文能夠解釋您需要的基礎數學,動機和直覺,並為您提供足夠的高級代碼來開始。請在評論中留下您的想法,快樂的黑客!

About Nanonets

Nanonets使得深度學習變得非常容易。

您可以使用自己的數據構建模型以實現高精度,並使用我們的API將其集成到您的應用程序中。

有關詳細信息,請訪問此處或通過info@nanonets.com與我們聯繫