你曾經是否去過一家管理良好的圖書館?我常常被圖書館有秩序的書籍管理震驚到,他們可以根據書名、內容或者其他主題把所有書排列整齊。但是如果你給圖書館提供了幾千本書,讓他們根據每本書的種類進行管理,他們一定會累到吐血。
但如果你有這些書的電子格式,做起來似乎就簡單的多了,無需手動操作,幾秒鐘可能就完成了。NLP萬歲!
請看下面一小段話:
從三種顏色的高亮處我們得知,這里有三種主題(或者概念)。一個好的主題模型可以分辨出相似的單詞,并把它們歸到一個群組中。在上面這段話中,最主要的主題就是綠色的主題2,通過它我們可以了解到這段話的主要意思是有關假視頻的。
在這篇文章中,我們將學習一種文本挖掘方法,稱為主題建模(topic modeling)。這是提取主題的一種非常有用的技術,在NLP問題中會經常用到。
注:在閱讀這篇文章前,我強烈推薦我們此前的另一篇文章:《12種降維方法終極指南(含Python代碼)》,從中可以了解SVD、UMAP等概念,這些概念會在本文出現。
什么是主題模型?
主題模型可以看作是一種無監督技術,用于在多個文本文件中發現主題。但這些主題在自然中是抽象的,而且一段文本中可能含有多種主題。就目前來說,我們暫且將主題模型理解成一個黑箱,如下圖所示:
黑箱(主題模型)將很多相似相關的詞語聚集起來,稱為主題。這些主題在文本中有特定的分布形態,每種主題都是通過它包含的不同單詞比例確定的。
什么時候會用到主題建模?
回到我們開頭說到的圖書館的例子,現在假設你要對幾個數字化文本進行管理,如果數量不多,完全可以手動完成,但如果電子文本數量很大該怎么辦?
這就需要用到NLP技術,對于這項任務,主題建模是必須用到的。
主題建??梢詭椭褂谜咛幚泶罅课谋緮祿?,找到文本中相似的多個詞語,確定抽象的主題。除此之外,主題模型還可以用于搜索引擎,讓搜索結果與搜索字符相匹配。
隱藏語義分析(LSA)概覽
所有語言都有自己細小的特征,機器難以分辨(有時連人類都會認錯)。比如有時不同的單詞卻表達相同含義,或者同一個單詞卻表達不同意思。
例如,看以下兩個句子:
I liked his lastnovelquite a lot.
We would like to go for anovelmarketing campaign.
在第一句話中,“novel”指的是一本書、小說,而在第二句話中它是形容詞,意為“新的”。
我們可以輕易地分辨二者,因為我們理解了“novel”前后詞語的意思。但是,機器無法理解這些概念,所以也不能理解詞語所處的語境。這就需要用到隱藏語義分析(LSA)了,它通過分析詞語周圍的語境捕捉其中的隱藏概念,即主題。
所以,僅僅將詞語映射到文本中并不能起到太大幫助,我們真正要做的是弄清楚詞語背后隱藏的概念或主題,這就是LSA的目的。
實施LSA的步驟
假設我們有m個文本文檔,總共有n個不同的詞語,我們想從文檔中所有文本數據中提取出k個主題,而k是由用戶決定的。
生成一個文本-單詞矩陣,計算TF-IDF分數。
之后,我們會將上述矩陣的維度降至k,利用奇異值分解(SVD)。
SVD將一個矩陣分解成三個其他的矩陣,假設我們想用SVD分解矩陣A,它就會將其分成矩陣U、S和VT(矩陣V的轉置矩陣)。
矩陣UK的每一行都是對應文本的向量表示,這些向量的長度是k,即目標主題的數量。我們數據中的詞語的向量表示可以在矩陣VK中找到。
通過SVD,我們得到了我們的數據中每個文本和詞語的向量表示,然后用這些向量,我們可以找到相似的單詞,利用余弦相似性找到相似的文本。
用Python實現LSA
首先下載所需要的庫。
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”,下載地址:archive.ics.uci.edu/ml/datasets/Twenty+Newsgroups。代碼如下:
from sklearn.datasets import fetch_20newsgroups
dataset = fetch_20newsgroups(shuffle=True, random_state=1, remove=('headers', 'footers', 'quotes'))
documents = dataset.data
len(documents)
輸出:11314。
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']
數據及共有11314個文本文檔,分布在20各不同的newsgroup中。
數據預處理
開始之前,我們先嘗試著清理文本數據。主要思想就是清除其中的標點、數字和特殊字符。之后,我們需要刪除較短的單詞,因為通常它們不會包含什么有用的信息。最后,我們將文本變為不區分大小寫。
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 notin 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
文本-詞語矩陣
這是通向主題建模的第一步。我們要用sklearn的TfidfVectorizer給1000個詞語創造一個文本-詞語矩陣。如果你有足夠的計算力,可以增加更多數據。
from sklearn.feature_extraction.text importTfidfVectorizer
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)
主題建模
下一步是將每個詞語和文本用向量表示,我們會用到文本-詞語矩陣并對他們降維。這里會用到TruncatedSVD執行矩陣的分解。
由于數據來自20個不同的分組,我們就假設文本數據有20個不同主題。
from sklearn.decomposition importTruncatedSVD
# 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
svdmodel中的元素就是我們的主題,我們可以用svdmodel.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(" ")
Topic0: like know people think good time thanks
Topic1: thanks windows card drive mail file advance
Topic2: game team year games season players good
Topic3: drive scsi disk hard card drives problem
Topic4: windows file window files program using problem
Topic5: government chip mail space information encryption data
Topic6: like bike know chip sounds looks look
Topic7: card sale video offer monitor price jesus
Topic8: know card chip video government people clipper
Topic9: good know time bike jesus problem work
Topic10: think chip good thanks clipper need encryption
Topic11: thanks right problem good bike time window
Topic12: good people windows know file sale files
Topic13: space think know nasa problem year israel
Topic14: space good card people time nasa thanks
Topic15: people problem window time game want bike
Topic16: time bike right windows file need really
Topic17: time problem file think israel long mail
Topic18: file need card files problem right good
Topic19: problem file thanks used space chip sale
主題可視化
為了更方便地探索主題,我們應該對其可視化。當然,可是話不能大于三維,但是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個分組。
完整代碼地址:github.com/prateekjoshi565/latentsemanticanalysis
LSA的優缺點
如上所示,隱藏語義分析非常有用,但是它也有自己的缺點。在使用它之前,還需要了解它的優缺點。
優點:
LSA非??欤⑶乙子趯嵤?/p>
結果很清晰,比單一的向量空間模型好得多。
缺點:
由于它是一個線性模型,可能在非線性數據集上表現的不是很好。
LSA假設文本中的詞語是高斯分布,可能不適用于所有問題。
LSA中涉及SVD,可能在出現新數據或更新時需要大量計算力。
-
模型
+關注
關注
1文章
3305瀏覽量
49221 -
SVD
+關注
關注
0文章
21瀏覽量
12194
原文標題:用隱藏語義分析(LSA)進行主題建模(附Python代碼)
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論