文本挖掘入門課:主題模型讓文本數據處理更幸福
全文共3480字,預計閱讀時長7分鐘
在解決自然語言處理的問題上,有一種文本挖掘的方法叫做主題模型,這是提取主題時一項極其有用的技術,那麼什麼是主題模型?何時使用主題模型?在Python中利用潛在語義分析來解決主題模型時,又應該注意哪些問題?讀完了本文,相信你一定會有最實在的收穫!
前言
你有沒有去過維護得相當完善的圖書館?那些圖書管理員非常讓人佩服,他們把圖書按照名稱、內容或主題進行歸類,一切都管理得井井有條。但是如果你扔給他們上千本圖書,然後讓他們按照書本的類型來整理好,他們可能一天都做不完,更不必說在一個小時之內了。
但是,如果這些書都是電子文本的話,整理工作可能就是幾秒鐘的事情,無需任何人力。自然語言處理萬歲!
先來看一下下面的文本片段:
參照有底色的文本,可以看到一共有三個主題(或者概念)——主題1、主題2和主題3。一個好的主題模型能夠辨別相似的片語,並把它們歸為一類。上面的例子中最明顯的主題是主題2,主要講偽造影像的內容。
有意思吧?好!本文介紹了一個叫做主題模型的文本挖掘方法。這是提取主題時一項極其有用的技術,在應對自然語言處理問題的時候也非常常見。
提示:強烈建議你閱讀這篇文章以對奇異值分解(SVD)和UMAP等概念進行了解(https://www.analyticsvidhya.com/blog/2018/08/dimensionality-reduction-techniques-python/)。本文是建立在這些概念之上的,因此先學習它們有利於鞏固我們對基礎概念的理解。
目錄
什麼是主題模型?
何時使用主題模型?
潛在語義分析(Latent Semantic Analysis, LSA)
在Python使用LSA
4.1 數據讀取和檢視
4.2 數據預處理
4.3 文本—詞語矩陣
4.4主題模型
4.5 主題可視化
LSA的優缺點
主題模型的其他技術
1.什麼是主題模型?
主題模型是一種無監督技術,用來發現各種文本文檔中的主題。這些主題本質上是抽象的,也就是說彼此相關的單詞會形成主題。 與此同時,單個文檔中可以有多個主題。本文中暫時將主題模型理解為黑盒子,如下圖所示:
這個黑盒子(也就是主題模型)把相關的片語劃分為不同的類群,稱之為主題。這些主題在文本中有特定的分布,每個主題都可以用不同比例的單片語合來定義。
2.何時使用主題模型?
回想一下之前提到的整理圖書的任務。現在想像一下,你需要對電子文檔來進行分類。當然,如果文檔比較少的話,你可以手動完成這個任務。但是如果文檔特別多的話怎麼辦?
這時候就要用自然語言處理技術了。而對於這個任務來說,將使用主題模型來完成。
主題模型可以幫助我們對海量的文本數據進行探索,對片語進行聚類,找到文本之間的相似性,並發現抽象的主題。如果你覺得這些任務還不夠有挑戰的話,主題模型還可以在搜索引擎中找到與搜索文本匹配的結果。是不是有點意思了?讓我們繼續深入探討!
3.潛在語義分析(Latent Semantic Analysis, LSA)
所有語言都會有自身的複雜性和微妙特徵,機器是難以捕捉這些內容的(有的時候人類自己也難以分辨)。比方說,不同的單詞可能會有相同的含義,而同樣的單詞又可能有不同的含義。
讓我們來看下面兩個句子:
1. I liked his last novel quite a lot.
2. We would like to go for a novel marketing campaign.
第一句話中,「novel」指代的是一本書,而第二句話中它表示新奇的、新穎的。
我們可以通過上下文輕易地推斷這兩個詞的含義,但是機器就捕捉不到這個概念因為它不能理解單詞所使用的語境。這時候就需要用到潛在語義分析了,它可以基於片語之間的上下文來揣摩背後的意思,也就是我們說的主題。
因此,單純地把片語映射到文檔中不一定有效果,我們需要的是搞懂詞語背後的概念和主題。潛在語義分析就是能夠找到隱藏主題的一種方法,現在讓我們來深入探討潛在語義分析的內部工作機制。
潛在語義分析的實現步驟
比方說我們有m個文檔,文檔中一共有n個唯一的詞,我們要從所有文檔中提取出k個主題。這裡k表示主題的數量,是由用戶自己定義的。
構造一個形如m * n的文檔—詞語矩陣,其中包含有TF-IDF分值。
然後,我們會把上述的矩陣用奇異值分解(SVD)的方法降到k維。
奇異值分解(SVD)把矩陣分解為三個矩陣。比如我們想要用奇異值分解(SVD)來降解矩陣A,那麼我們會得到矩陣U、矩陣S和矩陣VT(矩陣V的轉置矩陣)。矩陣Uk(文檔—片語矩陣)的每一行都是文檔的向量表示。這些向量的長度為k,也就是我們設定的主題數量。片語的向量表示可以在Vk(詞語—主題矩陣)中找到。
這樣一來,奇異值分解(SVD)把我們數據中的每個文檔和片語都進行了向量化,每個向量的長度都是k。我們可以結合餘弦相似度的方法,利用這些向量來找相似的片語和文檔。
4.在Python中使用潛在語義分析
下面我們介紹如何在Python中利用潛在語義分析來解決主題模型的問題。打開Python之後,可以按照我下面提到的步驟開始運行代碼。
4.1 數據讀取和檢視
首先要載入下面的包:
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=("headers", "footers", "quotes"))
documents = dataset.data
len(documents)
輸出: 11,314
dataset.target_names
["alt.atheism",
"comp.graphics",
"comp.os.ms-windows.misc",
"comp.sys.ibm.pc.hardware",
"comp.sys.mac.hardware",
"comp.windows.x",
"misc.forsale",
"rec.autos",
"rec.motorcycles",
"rec.sport.baseball",
"rec.sport.hockey",
"sci.crypt",
"sci.electronics",
"sci.med",
"sci.space",
"soc.religion.christian",
"talk.politics.guns",
"talk.politics.mideast",
"talk.politics.misc",
"talk.religion.misc"]
數據集包含來自20個不同新聞媒體的11,314份文本文檔。
4.2 數據預處理
開始,我們要儘可能對文本數據進行清洗。基本原則就是利用正則表達式,用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 text 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 if item 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
4.3 文本—詞語矩陣
這是創建主題模型的第一步。我們會用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。如果你有足夠的計算資源,我建議你可以把所有的詞語都涵蓋進去。
4.4 主題模型
下一步是把每個詞語和文檔用向量表示。我們會用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的要素(components)就是我們的主題,我們可以利用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 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
4.5 主題可視化
要知道我們的主題是否有特色,就需要進行可視化。當然,我們無法對三個維度以上的信息進行可視化。但是利用主成分分析(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的參數,看看圖片會有什麼變化。
文中所有代碼都可以在GitHub中找到。
(https://github.com/prateekjoshi565/latent_semantic_analysis)
5.LSA的優缺點
上面的例子中我們可以看到潛在語義分析的威力,但是它還是有自身局限性的。我們需要了解LSA的優缺點,這樣我們才知道什麼時候選用它,什麼時候應該嘗試別的方法。
優點:
LSA速度快,容易實現。
效果好,比平面向量空間模型要好得多。
缺點:
它是一個線性模型,因此在非線性依賴關係的數據集中表現不佳。
LSA假設詞語在文檔中呈正態分布,但不是所有問題都滿足這個假設。
LDA需要用到SVD,這是計算密集型的運算,在新數據加入後難以進行更新。
6.主題模型的其他技術
除了LSA之外,還有其他高級有效的主題模型技術,比如LDA和lda2Vec。我們還寫過一篇介紹LDA的好文章,可以給大家提供參考。Lda2vec是一個高級得多的主題模型方法,它是基於word2vec單詞嵌入的。
結束語
這篇文章中我分享了自己的學習收穫。主題模型是一個非常有意思的東西,它能幫助你處理許多文本數據集。因此,我建議大家利用本文的代碼來解決其他數據集的問題。享受文本挖掘吧!
留言 點贊 發個朋友圈
我們一起分享AI學習與發展的乾貨
編譯組: 黃天元、胡婷
相關鏈接:
https://www.analyticsvidhya.com/blog/2018/10/stepwise-guide-topic-modeling-latent-semantic-analysis/
如需轉載,請後台留言,遵守轉載規範
※周末AI課堂:深度學習中的熵 理論篇
※今日芯聲 | 拒絕大眾化!不整容也能讓你得到一張獨一無二的臉
TAG:讀芯術 |