python主題LDA建模和t-SNE可視化
原文鏈接:http://tecdat.cn/?p=4261
原文出處:拓端數據部落公眾號
?
使用潛在Dirichlet分配(LDA)和t-SNE中的可視化進行主題建模。
本文中的代碼片段僅供您在閱讀時更好地理解。有關完整的工作代碼,請參閱完整資料。
我們將首先介紹主題建模和t-SNE,然后將這些技術應用于兩個數據集:20個新聞組和推文。
什么是主題建模?
主題模型是一套算法/統計模型,可以揭示文檔集中的隱藏主題。文檔通常涉及不同比例的多個主題,特別是在跨學科文檔中(例如,60%關于生物學,25%關于統計學,15%關于計算機科學的生物信息學文章)。主題模型在數學框架中檢查和發(fā)現主題可能是什么以及每個文檔的主題可能性。
熱門話題建模算法包括潛在語義分析(LSA),分層Dirichlet過程(HDP)和潛在Dirichlet分配(LDA),其中LDA在實踐中已經顯示出很好的結果,因此被廣泛采用。這篇文章將使用LDA進行主題建模。
T-SNE
t-SNE或t分布隨機鄰域嵌入是用于高維數據可視化的維數降低算法。這部分是為了減輕人類不能(至少現在不能)感知超過3-D的向量空間這一事實。
這是一個降維并在三維空間中可視化的示例(信用:Google嵌入項目)

t-SNE是不確定的,其結果取決于數據批次。換句話說,相對于批次中的其他數據點,相同的高維數據點可以被轉換成不同批次的不同2-D或3-D向量。
可以使用各種語言實現t-SNE,但速度可能會有所不同。
環(huán)境
15-inch MacBook Pro, macOS Sierra
2.2 GHz Intel Core i7 processor
16 GB 1600 MHz DDR3 memory
1.將10,000 x 50矩陣轉換為10,000 x 2
C ++和Python
real 1m2.662s
user 1m0.575s
sys 0m1.929s
Python sklearn
real 3m29.883s
user 2m22.748s
sys 1m7.010s
2.將20,000 x 50矩陣轉換為20,000 x 2
C ++和Python
real 2m40.250s
user 2m32.400s
sys 0m6.420s
Python sklearn
real 6m54.163s
user 4m17.524s
sys 2m31.693s
3.將1,000,000 x 25矩陣轉換為1,000,000 x 2
C ++和Python
real 224m55.747s
user 216m21.606s
sys 8m21.412s
Python sklearn
out of memory... :(
t-SNE的作者說,他們“已經將這項技術應用于數據集,最多有3000萬個例子”(盡管他沒有指定數據和運行時的維度)。如果你有一個更大的數據集,你可以擴大你的硬件,調整參數(例如,sklearn的t-SNE中的angle參數),或嘗試替代(如LargeVis,其作者聲稱“與tSNE比較,LargeVis顯著降低了圖形構建步驟的計算成本“。我還沒有測試過它。
把它放在一起:20個新聞組的例子
在本節(jié)中,我們將在20個新聞組數據集上應用LDA算法,以發(fā)現每個文檔中的基礎主題,并使用t-SNE將它們顯示為組。
獲取數據
sklearn具有檢索和過濾20個新聞組數據的功能:
from sklearn.datasets import fetch_20newsgroups
remove?=?('headers', 'footers', 'quotes')
newsgroups_train?=?fetch_20newsgroups(subset?='train', remove?=remove)
newsgroups_test?=?fetch_20newsgroups(subset?='test', remove?=remove)
news?=?[' '?.join(filter(unicode?.isalpha, raw?.lower()?.split()))?for?raw?in
newsgroups_train?.data?+?newsgroups_test?.data]
?
LDA模型
在我們獲得清理后的數據后,我們可以對數據進行矢量化并訓練LDA模型:
import lda
from sklearn.feature_extraction.text import CountVectorizer
n_topics?=?20 # 主題數目
n_iter?=?500 # 循環(huán)次數
cvectorizer?=?CountVectorizer(min_df?=5, stop_words?='english')
cvz?=?cvectorizer?.fit_transform(news)
lda_model?=?lda?.LDA(n_topics?=n_topics, n_iter?=n_iter)
X_topics?=?lda_model?.fit_transform(cvz)
?
其中X_topics是18,846(num_news)乘20(n_topics)矩陣。注意,我們在這里有一個很好的概率解釋:每一行是屬于某個主題的這個新聞的概率分布(由我們的LDA模型學習)(例如,X_topics[0][0]代表屬于主題1的第一個新聞的可能性)。
用t-SNE減少到2-D
我們有一個學習過的LDA模型。但我們無法直觀地檢查我們的模型有多好。t-SNE來分析:
from sklearn.manifold import TSNE
tsne_model?=?TSNE(n_components?=2, verbose?=1, random_state?=0, angle?=.99, init='pca')
# 20-D -> 2-D
tsne_lda?=?tsne_model?.fit_transform(X_topics)
?
可視化組及其關鍵字
現在,我們已準備好使用流行的Python可視化庫來可視化新聞組和關鍵字。
首先我們做一些設置工作(導入類和函數,設置參數等):
import numpy?as?np
import bokeh.plotting?as?bp
from bokeh.plotting import save
from bokeh.models import HoverTool
n_top_words?=?5
colormap?=?np?.array([
"#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
"#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5",
"#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f",
"#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5"
])
?
然后我們找到每個新聞最可能的主題:
_lda_keys?=?[]
for?i?in?xrange(X_topics?.shape[0]):
_lda_keys?+=?_topics[i]?.argmax(),
并獲得每個主題的頂級單詞:
topic_summaries?=?[]
topic_word?=?lda_model?.topic_word_ # 所有主題關鍵詞
vocab?=?cvectorizer?.get_feature_names()
for?i, topic_dist?in?enumerate(topic_word):
topic_words?=?np?.array(vocab)[np?.argsort(topic_dist)][:?-(n_top_words?+?1):?-1] # 獲得數據
topic_summaries?.append(' '?.join(topic_words)) # 加到單詞列表
?
我們繪制新聞(每個點代表一個新聞):
title?=?'20 newsgroups LDA viz'
num_example?=?len(X_topics)
plot_lda?=?bp?.figure(plot_width?=1400, plot_height?=1100,
title?=title,
tools?="pan,wheel_zoom,box_zoom,reset,hover,previewsave",
x_axis_type?=None, y_axis_type?=None, min_border?=1)
plot_lda?.scatter(x?=tsne_lda[:, 0], y?=tsne_lda[:, 1],
color?=colormap[_lda_keys][:num_example],
source?=bp?.ColumnDataSource({
"content": news[:num_example],
"topic_key": _lda_keys[:num_example]
}))
#繪制每個主題的關鍵詞:
topic_coord?=?np?.empty((X_topics?.shape[1], 2))?*?np?.nan
for?topic_num?in?_lda_keys:
if?not?np?.isnan(topic_coord)?.any():
break
topic_coord[topic_num]?=?tsne_lda[_lda_keys?.index(topic_num)]
for?i?in?xrange(X_topics?.shape[1]):
plot_lda?.text(topic_coord[i, 0], topic_coord[i, 1], [topic_summaries[i]])
hover?=?plot_lda?.select(dict(type?=HoverTool))
hover?.tooltips?=?{"content": "@content - topic: @topic_key"}
save(plot_lda, '{}.html'?.format(title))
?
你會得到一個像這樣的交互式圖表:


當我們?yōu)槊總€文檔分配一個主要主題時,有些情況最可能的主題的概率相當低(極端情況是每個主題被分配5%,即,均勻分布)。換句話說,我們的模型無法為這樣的新聞分配主題。
一種解決方法是添加一個閾值因子,以幫助過濾掉低置信的分配。在我們訓練LDA模型之后,使用t-SNE減少維數之前,簡單地說明:
import numpy
threshold?=?0.5
_idx?=?np?.amax(X_topics, axis?=1)?>?threshold
X_topics?=?X_topics[_idx]
?
并重新運行我們將得到的代碼:

看起來好多了:獨立和明確的簇!
推文示例
Twitter已成為最受歡迎的新聞和社交網絡服務(SNS)平臺之一。我們也可以使用推文語料庫來模擬主題。
我們希望將推文保存到磁盤并積累一定數量(至少數百萬)來有效地模擬主題,而不是將推文放在內存中進行實時處理。
首先,我們需要建立一個推文連接,我們可以抓取實時推文:
至少花一兩天時間來積累相當數量的推文。有時連接可能會中斷:只需重新運行腳本,以便將新推文保存到磁盤。
獲得足夠的推文后,我們可以加載推文,處理它們,對它們進行矢量化并計算tf-idf分數,訓練LDA模型,減少到2-D,并可視化結果。請參閱此處的完整腳本。
你會得到一個如下圖:


這是對200萬條推文進行過訓練的模型的可視化,只顯示了5,000個數據點(或推文)。我們有一些很好的集群學習模型: “視頻點贊新”代表社交網絡內容。
?

參考文獻
1.matlab偏最小二乘回歸(PLSR)和主成分回歸(PCR)
2.R語言高維數據的主成分pca、 t-SNE算法降維與可視化分析
3.主成分分析(PCA)基本原理及分析實例
4.基于R語言實現LASSO回歸分析
5.使用LASSO回歸預測股票收益數據分析
6.r語言中對lasso回歸,ridge嶺回歸和elastic-net模型
7.r語言中的偏最小二乘回歸pls-da數據分析
8.r語言中的偏最小二乘pls回歸算法
9.R語言線性判別分析(LDA),二次判別分析(QDA)和正則判別分析(RDA)
?