python主題LDA建模和t-SNE可視化

原文:http://tecdat.cn/?p=4261html

使用潛在Dirichlet分配(LDA)和t-SNE中的可視化進行主題建模。算法

本文中的代碼片斷僅供您在閱讀時更好地理解。有關完整的工做代碼,請參閱此回購。網絡

咱們將首先介紹主題建模和t-SNE,而後將這些技術應用於兩個數據集:20個新聞組和推文。app

什麼是主題建模?

主題模型是一套算法/統計模型,能夠揭示文檔集中的隱藏主題。直觀地看,由於一個文件是關於某個特定話題,人們所指望的某些詞出如今文檔中或多或少頻繁:「算法」,「編譯器」,和「陣」將在大約計算機科學文檔更常常出現,「關於政治的文件中的民主','政治家'和'政策',''','a'和'是'二者均可能一樣出現。此外,文檔一般涉及不一樣比例的多個主題,特別是在跨學科文檔中(例如,60%關於生物學,25%關於統計學,15%關於計算機科學的生物信息學文章)。主題模型在數學框架中捕獲這種直覺,以檢查和發現主題多是什麼以及每一個文檔的主題平衡。框架

熱門話題建模算法包括潛在語義分析(LSA),分層Dirichlet過程(HDP)和潛在Dirichlet分配(LDA),其中LDA在實踐中已經顯示出很好的結果,所以被普遍採用。這篇文章將使用LDA進行主題建模(對於那些喜歡瞭解LDA理論而且閱讀公式很舒服的人,請參閱本文)。less

T-SNE

t-SNE或t分佈隨機鄰域嵌入是用於高維數據可視化的維數下降算法。這部分是爲了減輕人類不能(至少如今不能)感知超過3-D的向量空間這一事實。dom

這是一個減小784-D數字表示並在三維空間中可視化的示例(信用:Google嵌入項目)函數

t-SNE是不肯定的,其結果取決於數據批次。換句話說,相對於批次中的其餘數據點,相同的高維數據點能夠被轉換成不一樣批次的不一樣2-D或3-D向量。學習

可使用各類語言實現t-SNE,但速度可能會有所不一樣。例如,我對C ++和Python包裝器以及Python sklearn版本進行了比較,發現前者在矩陣轉換速度方面一般快3倍:測試

環境

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個新聞組的例子

足夠的理論:讓咱們親自動手吧。在本節中,咱們將在20個新聞組數據集上應用LDA算法,以發現每一個文檔中的基礎主題,並使用t-SNE將它們顯示爲組。

獲取數據

幸運的是,它sklearn具備輕鬆檢索和過濾20個新聞組數據的功能:

from sklearn.datasets import fetch_20newsgroups
# we only want to keep the body of the documents!
remove = ('headers', 'footers', 'quotes')
# fetch train and test data
newsgroups_train = fetch_20newsgroups(subset ='train', remove =remove)
newsgroups_test = fetch_20newsgroups(subset ='test', remove =remove)
# a list of 18,846 cleaned news in string format
# only keep letters & make them all lower case
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 # number of topics
n_iter = 500 # number of iterations
# vectorizer: ignore English stopwords & words that occur less than 5 times
cvectorizer = CountVectorizer(min_df =5, stop_words ='english')
cvz = cvectorizer .fit_transform(news)
# train an LDA model
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
# a t-SNE model
# angle value close to 1 means sacrificing accuracy for speed
# pca initializtion usually leads to better results
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 # number of keywords we show
# 20 colors
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_ # all topic words
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] # get!
topic_summaries .append(' ' .join(topic_words)) # append!

最後但並不是最不重要的是,咱們繪製新聞(每一個點表明一個新聞):

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]
}))
並繪製每一個主題的關鍵詞:

# randomly choose a news (within a topic) coordinate as the crucial words coordinate
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)]
# plot crucial words
for i in xrange(X_topics .shape[1]):
plot_lda .text(topic_coord[i, 0], topic_coord[i, 1], [topic_summaries[i]])
# hover tools
hover = plot_lda .select(dict(type =HoverTool))
hover .tooltips = {"content": "@content - topic: @topic_key"}
# save the plot
save(plot_lda, '{}.html' .format(title))

這是不少代碼...但若是你已經作到這一點,你會獲得一個像這樣的交互式情節:

當咱們爲每一個文檔分配一個主要主題時,有些狀況甚至最可能的主題的機率至關低(極端狀況是每一個主題被分配5%,即,均勻分佈)。換句話說,咱們的模型沒法自信(利潤率很高)爲這樣的新聞分配主題。

一種解決方法是添加一個閾值因子,以幫助過濾掉非自信的分配。在咱們訓練LDA模型以後,在咱們使用t-SNE減小維數以前,簡單地說明這些線:

import numpy
threshold = 0.5
_idx = np .amax(X_topics, axis =1) > threshold # idx of doc that above the threshold
X_topics = X_topics[_idx]

並從新運行咱們將獲得的代碼:

看起來好多了:孤立和明確的團體!然而,咱們以犧牲非自信的任務爲代價來實現這一目標(在這種狀況下,超過一半的數據)。這代表咱們的LDA模型只能從這個數據集中學到不少,並且咱們的模型沒有信心爲全部新聞分配一個好的主題。

也就是說,若是你仔細檢查每一個主題,那麼爲每一個主題學到的熱門話語都有必定道理:例如,'醫療保健使用號碼患者'(醫療保健)反對'god jesus christian bible'(宗教)。

推文示例

Twitter已成爲最受歡迎的新聞和社交網絡服務(SNS)平臺之一。在上一篇博客實時Twitter趨勢發現中,咱們討論瞭如何實時可視化Twitter趨勢。然而,咱們也可使用推文語料庫來模擬主題。

咱們但願將推文保存到磁盤並積累必定數量(至少數百萬)來有效地模擬主題,而不是將推文放在內存中進行實時處理。

首先,咱們須要創建一個推文鏈接:請查看本節的內容。憑藉憑據,咱們能夠抓取實時推文:

至少花一兩天時間來積累至關數量的推文。有時鏈接可能會中斷:只需從新運行腳本,以便將新推文保存到磁盤。

得到足夠的推文後,咱們能夠加載推文,處理它們,對它們進行矢量化並計算tf-idf分數,訓練LDA模型,減小到2-D,並可視化結果。請參閱此處的完整腳本。

你會獲得一個以下圖:

這是對200萬條推文進行過培訓的模型的可視化,只顯示了5,000個數據點(或推文)。咱們有一些很好的集羣學習模型:'性女孩色情'表明一些色情相關的推文,'視頻喜歡新'表明社交網絡內容,'特朗普希拉里cliton'表明政治和選舉 。

相關文章
相關標籤/搜索