教你在Python中實現潛在語義分析
作者:PRATEEK JOSHI
翻譯:李潤嘉
校對:萬文菁
本文約3400字,建議閱讀15分鐘。
本文將通過拆解LSA的原理及代碼實例來講解如何運用LSA進行潛在語義分析。
介紹
你有沒有去過那種運營良好的圖書館?我總是對圖書館館員通過書名、內容或其他主題保持一切井井有條的方式印象深刻。但是如果你給他們數千本書,要求他們根據書的種類整理出來,他們很難在一天內完成這項任務,更不用說一小時!
但是,如果這些書以電子的形式出現,就難不倒你了,對吧?所有的整理會在幾秒之間完成,並且不需要任何人工勞動。自然語言處理(NLP)萬歲!
看看下面這段話:
你可以從高亮的詞語中總結出,這段話有三個主題(或概念)——主題1、主題2和主題3。一個良好的主題模型可以識別出相似的詞語並將它們放在一組或一個主題下。上述示例中最主要的主題是主題2,表明這段文字主要關於虛假視頻。
是不是很好奇?太好了!在本文中,我們將學習一種叫做主題建模的文本挖掘方法。這是一種非常有用的提取主題的技術,在面對NLP挑戰時你會經常使用到它。
注意:我強烈建議您通讀這篇文章了解SVD和UMAP等定義。它們在本文中經常出現,因此對它們有基本的理解有助於鞏固這些概念。
目錄
1. 什麼是主題模型?
2. 何時使用主題建模?
3. 潛在語義分析(LSA)概述
4. 在Python中實現LSA
數據讀取和檢查
數據預處理
文檔-詞項矩陣(Document-Term Matrix)
主題建模
主題可視化
5. LSA的優缺點
6. 其他主題建模技術
什麼是主題模型?
主題模型可定義為一種在大量文檔中發現其主題的無監督技術。這些主題本質上十分抽象,即彼此相關聯的詞語構成一個主題。同樣,在單個文檔中可以有多個主題。我們暫時將主題模型理解為一個如下圖所示的黑盒子:
這個黑盒子(主題模型)將相似和相關的詞語聚集成簇,稱為主題。這些主題在文檔中具有特定的分布,每個主題都根據它包含的不同單詞的比例來定義。
何時使用主題建模?
回想一下剛才提到的將相似的書籍整理到一起的例子。現在假設你要對一些電子文檔執行類似的任務。只要文檔的數量不太多,你就可以手動完成。但是如果這些文檔的數量非常多呢?
這就是NLP技術脫穎而出的地方。對於這個任務而言,主題建模非常適用。
主題建模有助於挖掘海量文本數據,查找詞簇,文本之間的相似度以及發現抽象主題。如果這些理由還不夠引人注目,主題建模也可用於搜索引擎,判斷搜索欄位與結果的匹配程度。越來越有趣了,是不是?那麼,請繼續閱讀!
潛在語義分析(LSA)概述
所有語言都有自己的錯綜複雜和細微差別,比如一義多詞和一詞多義,這對機器而言很難捕捉(有時它們甚至也被人類誤解了!)。
例如,如下兩個句子:
1. I liked his last novel quite a lot.
2. We would like to go for a novel marketing campaign.
在第一個句子中,"novel" 指一本書,而在第二個句子中,它的含義是新奇的、新穎的。
我們能夠輕鬆地區分這些單詞,是因為我們可以理解這些詞背後的語境。但是,機器並不能捕捉到這個概念,因為它不能理解單詞的上下文。這就是潛在語義分析(LSA)發揮作用的地方,它可以利用單詞所在的上下文來捕捉隱藏的概念,即主題。
因此,簡單地將單詞映射到文檔並沒有什麼用。我們真正需要的是弄清楚單詞背後的隱藏概念或主題。LSA是一種可以發現這些隱藏主題的技術。現在我們來深入探討下LSA的內部工作機制。
LSA的實施步驟
假設我們有m篇文檔,其中包含n個唯一詞項(單詞)。我們希望從所有文檔的文本數據中提取出k個主題。主題數k,必須由用戶給定。
生成一個m×n維的文檔-詞項矩陣(Document-Term Matrix),矩陣元素為TF-IDF分數
然後,我們使用奇異值分解(SVD)把上述矩陣的維度降到k(預期的主題數)維
SVD將一個矩陣分解為三個矩陣。假設我們利用SVD分解矩陣A,我們會得到矩陣U,矩陣S和矩陣VT(矩陣V的轉置)
矩陣Uk(document-term matrix)的每個行向量代表相應的文檔。這些向量的長度是k,是預期的主題數。代表數據中詞項的向量可以在矩陣Vk(term-topic matrix)中找到。
因此,SVD為數據中的每篇文檔和每個詞項都提供了向量。每個向量的長度均為k。我們可以使用餘弦相似度的方法通過這些向量找到相似的單詞和文檔。
在Python中實現LSA
是時候啟動Python並了解如何在主題建模問題中應用LSA了。開啟Python環境後,請按照如下步驟操作。
數據讀取和檢查
在開始之前,先載入需要的庫。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
pd.set_option("display.max_colwidth", 200)
在本文中,我們使用sklearn中的"20 Newsgroup"數據集,可從這裡下載,然後按照代碼繼續操作。
from sklearn.datasets import fetch_20newsgroups
dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=("header","footers",quotes"))
documents = dataset.data
len(documents)
Output: 11,314
Dataset.target_names
["alt.atheism",
"comp.graphics",
"comp.os.ms-windows.misc",
"misc.forsale",
"rec.autos",
"rec.motorcycles",
"sci.crypt",
"sci.electronics",
"sci.med",
"sci.space",
該數據集包含分布在20個不同新聞組中的11314篇文檔。
數據預處理
首先,我們嘗試儘可能地清理文本數據。我們的想法是,使用正則表達式replace("[^a-zA-Z#]", " ")一次性刪除所有標點符號、數字和特殊字元,這個正則表達式可以替換除帶空格的字母之外的所有內容。然後刪除較短的單詞,因為它們通常並不包含有用的信息。最後,將全部文本變為小寫,使得大小寫敏感失效。
news_df = pd.DataFrame({"document":documents})
# removing everything except alphabets
news_df["clean_doc"] = news_df["document"].str.replace("[^a-zA-Z#]", " ")
# removing short words
news_df["clean_doc"] = news_df["clean_doc"].apply(lambda x: " ".join([w for w in x.split() if len(w)>3]))
# make all the lowercase
news_df["clean_doc"] = news_df["clean_doc"].apply(lambda x: x.lower())
最好將文本數據中的停止詞刪除,因為它們十分混亂,幾乎不攜帶任何信息。停止詞是指"it", "they", "am", "been", "about", "because", "while"之類的辭彙。
要從文檔中刪除停止詞,我們必須對文本進行標記,將文本中的字元串拆分為單個的標記或單詞。刪除完停止詞後,我們將標記重新拼接到一起。
from nltk.corpus import stopwords
stop_words = stopwords.words("english")
# tokenization
tokenized_doc = news_df["clean_doc"].apply(lambda x: x.split())
# remove stop-words
tokenized_doc = tokenized_doc.apply(lambda x: [item for item in x ifitem not in stop_words])
# de-tokenization
detokenized_doc = []
for i in range(len(news_df)):
t = " ".join(tokenized_doc[i])
detokenized_doc.append(t)
news_df["clean_doc"] = detokenized_doc
文檔-詞項矩陣(Document-Term Matrix)
這是主體建模的第一步。我們將使用sklearn的TfidfVectorizer來創建一個包含1000個詞項的文檔-詞項矩陣。
from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer = TfidfVectorizer(stop_words="english",
max_features =1000, # keep top 1000 terms
max_df = 0.5,
smooth_idf = True)
X = vectorizer.fit_transform(news_df["clean_doc"])
X.shape # check shape of the document-term matrix
(11314, 1000)
我們也可以使用全部詞項來創建這個矩陣,但這回需要相當長的計算時間,並佔用很多資源。因此,我們將特徵的數量限制為1000。如果你有計算能力,建議嘗試使用所有詞項。
主題建模
下一步是將每個詞項和文本表示為向量。我們將使用文本-詞項矩陣,並將其分解為多個矩陣。我們將使用sklearn的TruncatedSVD來執行矩陣分解任務。
由於數據來自20個不同的新聞組,所以我們打算從文本數據中提取出20個主題。可以使用n_components參數來制定主題數量。
from sklearn.decomposition import TruncatedSVD
# SVD represent documents and terms in vectors
svd_model = TruncatedSVD(n_components=20, algorithm="randomized", n_iter=100, random_state=122)
svd_model.fit(X)
len(svd_model.components_)
20
svd_model的組成部分即是我們的主題,我們可以通過svd_model.components_來訪問它們。最後,我們列印出20個主題中前幾個最重要的單詞,看看我們的模型都做了什麼。
terms = vectorizer.get_feature_names()
for i, comp in enumerate(svd_model.components_):
terms_comp = zip(terms, comp)
sorted_terms = sorted(terms_comp, key=lambda x:x[1], reverse=True)[:7]
print("Topic "+str(i)+": ")
for t in sorted_terms:
print(t[0])
print(" ")
Topic 0: like know people think good time thanks
Topic 0: like know people think good time thanks
Topic 1: thanks windows card drive mail file advance
Topic 2: game team year games season players good
Topic 3: drive scsi disk hard card drives problem
Topic 4: windows file window files program using problem
Topic 5: government chip mail space information encryption data
Topic 6: like bike know chip sounds looks look
Topic 7: card sale video offer monitor price jesus
Topic 8: know card chip video government people clipper
Topic 9: good know time bike jesus problem work
Topic 10: think chip good thanks clipper need encryption
Topic 11: thanks right problem good bike time window
Topic 12: good people windows know file sale files
Topic 13: space think know nasa problem year israel
Topic 14: space good card people time nasa thanks
Topic 15: people problem window time game want bike
Topic 16: time bike right windows file need really
Topic 17: time problem file think israel long mail
Topic 18: file need card files problem right good
Topic 19: problem file thanks used space chip sale
主題可視化
為了找出主題之間的不同,我們將其可視化。當然,我們無法可視化維度大於3的數據,但有一些諸如PCA和t-SNE等技術可以幫助我們將高維數據可視化為較低維度。在這裡,我們將使用一種名為UMAP(Uniform Manifold Approximation and Projection)的相對較新的技術。
import umap
X_topics = svd_model.fit_transform(X)
embedding = umap.UMAP(n_neighbors=150, min_dist=0.5, random_state=12).fit_transform(X_topics)
plt.figure(figsize=(7,5))
plt.scatter(embedding[:, 0], embedding[:, 1],
c= dataset.target,
s= 10, # size
edgecolor="none"
)
plt.show()
如上所示,結果非常漂亮。每個點代表一個文檔,顏色代表20個新聞組。我們的LSA模型做得很好。可以任意改變UMAP的參數來觀察其對圖像的影響。
可在此找到本文的完整代碼。
LSA的優缺點
如上所述,潛在語義分析非常有用,但是確實有其局限性。因此,對LSA的優缺點都有充分的認識十分重要,這樣你就知道何時需要使用LSA,以及何時需要嘗試其他方法。
優點:
LSA快速且易於實施。
它的結果相當好,比簡單的向量模型強很多。
缺點:
因為它是線性模型,因此在具有非線性依賴性的數據集上可能效果不佳。
LSA假設文本中的詞項服從正態分布,這可能不適用於所有問題。
LSA涉及到了SVD,它是計算密集型的,當新數據出現時難以更新。
其他主題建模技術
尾記
本文意於與大家分享我的學習經驗。主題建模是個非常有趣的話題,當你在處理文本數據集時會用到許多技巧和方法。因此,我敦促大家使用本文中的代碼,並將其應用於不同的數據集。如果您對本文有任何疑問或反饋,請與我們聯繫。快樂地去挖掘文本吧!
原文標題:
Text Mining 101: A Stepwise Introduction to Topic Modeling using Latent Semantic Analysis (using Python)
https://www.analyticsvidhya.com/blog/2018/10/stepwise-guide-topic-modeling-latent-semantic-analysis/
譯者簡介
李潤嘉,首都師範大學應用統計碩士在讀。對數據科學和機器學習興趣濃厚,語言學習愛好者。立志做一個有趣的人,學想學的知識,去想去的地方,敢想敢做,不枉歲月。
翻譯組招募信息
工作內容:需要一顆細緻的心,將選取好的外文文章翻譯成流暢的中文。如果你是數據科學/統計學/計算機類的留學生,或在海外從事相關工作,或對自己外語水平有信心的朋友歡迎加入翻譯小組。
你能得到:定期的翻譯培訓提高志願者的翻譯水平,提高對於數據科學前沿的認知,海外的朋友可以和國內技術應用發展保持聯繫,THU數據派產學研的背景為志願者帶來好的發展機遇。
其他福利:來自於名企的數據科學工作者,北大清華以及海外等名校學生他們都將成為你在翻譯小組的夥伴。
點擊文末「閱讀原文」加入數據派團隊~
轉載須知
如需轉載,請在開篇顯著位置註明作者和出處(轉自:數據派ID:datapi),並在文章結尾放置數據派醒目二維碼。有原創標識文章,請發送【文章名稱-待授權公眾號名稱及ID】至聯繫郵箱,申請白名單授權並按要求編輯。
發布後請將鏈接反饋至聯繫郵箱(見下方)。未經許可的轉載以及改編者,我們將依法追究其法律責任。
點擊「閱讀原文」擁抱組織
※近期活動盤點:AI超級用戶增長引擎、眾智創新賽
※一文讀懂Corda分散式記賬技術
TAG:數據派THU |