原文: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分佈隨機鄰域嵌入是用於高維數據可視化的維數下降算法。這部分是爲了減輕人類不能(至少如今不能)感知超過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個新聞組數據集上應用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模型:
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的第一個新聞的可能性)。
咱們有一個學習過的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'表明政治和選舉 。