什麼是Mahout?
” Apache Mahout™ project’s goal is to build a scalable machine learning library ”
我來拓展一下:
(1) Mahout 是Apache旗下的開源項目,集成了大量的機器學習算法。
(2) 大部分算法,可以運行在Hadoop上,具有很好的拓展性,使得大數據上的機器學習成爲可能。
本篇主要探討 Mahout 0.9 中的聚類(Clustering)工具的用法。
一、數據準備
Mahout聚類算法的輸入爲List<Vector>,即需要將每個待聚類的文檔,表示爲向量形式。
在本文中,我們選擇經典的 Reuters21578 文本語料。嘗試對新聞內容進行文本聚類。
1、下載數據
| axel -n 20 http://kdd.ics.uci.edu/databases/reuters21578/reuters21578.tar.gz |
2、解壓縮數據
| tar -xzvf ./reuters21578.tar.gz ./reuters-sgm |
解壓縮之後,reuters-sgm下,包含了若干*.sgm文件,每個文件中又包含了若干下屬結構化文檔:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <REUTERS TOPICS="NO" LEWISSPLIT="TRAIN" CGISPLIT="TRAINING-SET" OLDID="5545" NEWID="2"> <DATE>26-FEB-1987 15:02:20.00</DATE> <TOPICS></TOPICS> <PLACES><D>usa</D></PLACES> <PEOPLE></PEOPLE> <ORGS></ORGS> <EXCHANGES></EXCHANGES> <COMPANIES></COMPANIES> <UNKNOWN> F Y f0708reute d f BC-STANDARD-OIL-<SRD>-TO 02-26 0082</UNKNOWN> <TEXT> <TITLE>STANDARD OIL <SRD> TO FORM FINANCIAL UNIT</TITLE> <DATELINE> CLEVELAND, Feb 26 - </DATELINE><BODY>Standard Oil Co and BP North America Inc said they plan to form a venture to manage the money market borrowing and investment activities of both companies. BP North America is a subsidiary of British Petroleum Co Plc <BP>, which also owns a 55 pct interest in Standard Oil. The venture will be called BP/Standard Financial Trading and will be operated by Standard Oil under the oversight of a joint management committee. Reuter </BODY></TEXT> </REUTERS> |
在下文中,我們主要使用<TITLE>和<BODY>中的文本。即標題+正文。
3、抽取
Mahout中內置了對上述Reuters預料的抽取程序,我們可以直接使用。
| mahout org.apache.lucene.benchmark.utils.ExtractReuters ./reuters-sgm ./reuters-out |
如上所述,抽取好的結果在./reuters-out文件夾下面,每篇<REUTERS>文檔,變成了一個獨立的文件。
一共有21578個txt,即數據集中含有21578篇文檔:-)
說下命名規則吧,例如:文件名:./reuters-out/reut2-006.sgm-246.txt,表示來自於./reuters-sgm/reut2-006.sgm中的第246篇文檔,下標從0開始。
4、轉換成SequenceFile
對於傳統的文本聚類算法而言,下一步應該是:將文本轉化爲詞的向量空間表示。
然而,不要太着急哦。
由於Mahout運行在Hadoop上,HDFS是爲大文件設計的。如果我們把上述21578個txt都拷貝上去,這樣是非常不合適的
設想下:假設對1000萬篇新聞進行聚類,難道要拷貝1000w個文件麼?這會把name node搞掛的。
因此,Mahout採用SequenceFile作爲其基本的數據交換格式。
內置的seqdirectory命令(這個命令設計的不合理,應該叫directoryseq纔對),可以完成 文本目錄->SequenceFile的轉換過程。
| mahout seqdirectory -i file://$(pwd)/reuters-out/ -o file://$(pwd)/reuters-seq/ -c UTF-8 -chunk 64 -xm sequential |
上述命令蘊含了2個大坑,在其他文檔中均沒有仔細說明:
(1) -xm sequential,表示在本地執行,而不是用MapReduce執行。如果是後者,我們勢必要將這些小文件上傳到HDFS上,那樣的話,還要SequenceFile做甚……
(2) 然而seqdirectory在執行的時候,並不因爲十本地模式,就在本地文件系統上尋找。而是根據-i -o的文件系統前綴來判斷文件位置。也就是說,默認情況,依然十在HDFS上查找的……所以,這個file://的前綴是非常有必要的。
其他2個參數:
- -c UTF8:編碼。
- -chunk 64:64MB一個Chunk,應該和HDFS的BLOCK保持一致或者倍數關係。
5、轉換爲向量表示
爲了適應多種數據,聚類算法多使用向量空間作爲輸入數據。
首先在HDFS 上創建目錄user/coder4
hadoop fs -mkdir user/coder4
由於我們先前已經得到了處理好的SequenceFile,從這一步開始,就可以在Hadoop上進行啦。
| hadoop dfs -put reuters-seq /user/coder4 |
開始text->Vector的轉換:
| mahout seq2sparse -i /user/coder4/reuters-seq -o /user/coder4/reuters-sparse -ow --weight tfidf --maxDFPercent 85 --namedVector |
輸入和輸出不解釋了。在Mahout中的向量類型可以稱爲sparse。
參數說明如下:
- -ow( 或 –overwrite):即使輸出目錄存在,依然覆蓋。
- –weight(或 -wt) tfidf:權重公式,大家都懂的。其他可選的有tf (當LDA時建議使用)。
- –maxDFPercent(或 -x) 85:過濾高頻詞,當DF大於85%時,將不在作爲詞特徵輸出到向量中。
- –namedVector (或-nv):向量會輸出附加信息。
其他可能有用的選項:
- –analyzerName(或-a):指定其他分詞器。
- –minDF:最小DF閾值。
- –minSupport:最小的支持度閾值,默認爲2。
- –maxNGramSize(或-ng):是否創建ngram,默認爲1。建議一般設定到2就夠了。
- –minLLR(或 -ml):The minimum Log Likelihood Ratio。默認爲1.0。當設定了-ng > 1後,建議設置爲較大的值,只過濾有意義的N-Gram。
- –logNormalize(或 -lnorm):是否對輸出向量做Log變換。
- –norm(或 -n):是否對輸出向量做p-norm變換,默認不變換。
看一下產出:
| hadoop dfs -ls /user/coder4/reuters-sparse Found 7 items /user/coder4/reuters-sparse/df-count /user/coder4/reuters-sparse/dictionary.file-0 /user/coder4/reuters-sparse/frequency.file-0 /user/coder4/reuters-sparse/tf-vectors /user/coder4/reuters-sparse/tfidf-vectors /user/coder4/reuters-sparse/tokenized-documents /user/coder4/reuters-sparse/wordcount |
說明各個文件的用途:
- dictionary.file-0:詞文本 -> 詞id(int)的映射。詞轉化爲id,這是常見做法。
- frequency.file:詞id -> 文檔集詞頻(cf)。
- wordcount(目錄): 詞文本 -> 文檔集詞頻(cf),這個應該是各種過濾處理之前的信息。
- df-count(目錄): 詞id -> 文檔頻率(df)。
- tf-vectors、tfidf-vectors (均爲目錄):詞向量,每篇文檔一行,格式爲{詞id:特徵值},其中特徵值爲tf或tfidf。有用採用了內置類型VectorWritable,需要用命令”mahout vectordump -i <path>”查看。
- tokenized-documents:分詞後的文檔。
二、KMeans
1、運行K-Means
| mahout kmeans -i /user/coder4/reuters-sparse/tfidf-vectors -c /user/coder4/reuters-kmeans-clusters -o /user/coder4/reuters-kmeans -k 20 -dm org.apache.mahout.common.distance.CosineDistanceMeasure -x 200 -ow --clustering |
參數說明如下:
- -i:輸入爲上面產出的tfidf向量。
- -o:每一輪迭代的結果將輸出在這裏。
- -k:幾個簇。
- -c:這是一個神奇的變量。若不設定k,則用這個目錄裏面的點,作爲聚類中心點。否則,隨機選擇k個點,作爲中心點。
- -dm:距離公式,文本類型推薦用cosine距離。
- -x :最大迭代次數。
- –clustering:在mapreduce模式運行。
- –convergenceDelta:迭代收斂閾值,默認0.5,對於Cosine來說略大。
輸出1,初始隨機選擇的中心點:
| hadoop dfs -ls /user/coder4/reuters-kmeans-clusters Found 1 items /user/coder4/reuters-kmeans-clusters/part-randomSeed |
輸出2,聚類過程、結果:
| hadoop dfs -ls /user/coder4/reuters-kmeans Found 5 items /user/coder4/reuters-kmeans/_policy /user/coder4/reuters-kmeans/clusteredPoints /user/coder4/reuters-kmeans/clusters-0 /user/coder4/reuters-kmeans/clusters-1 /user/coder4/reuters-kmeans/clusters-2-final |
其中,clusters-k(-final)爲每次迭代後,簇的20箇中心點的信息。
而clusterdPoints,存儲了 簇id -> 文檔id 的映射。
2、查看簇結果
首先,用clusterdump,來查看k(20)個簇的信息。
| # Get to Local hdfs dfs -get /user/coder4/reuters-kmeans/ ./ hadoop dfs -get /user/coder4/reuters-sparse/ ./ # View .. mahout clusterdump -i /user/coder4/reuters-kmeans/clusters-2-final -d ./reuters-sparse/dictionary.file-0 -dt sequencefile -o ./reuters-kmeans-cluster-dump/ -n 20 |
要說明的是,clusterdump似乎只能在本地執行……所以先把數據下載到本地吧。
參數說明:
- -i :我們只看最終迭代生成的簇結果。
- -d :使用 詞 -> 詞id 映射,使得我們輸出結果中,可以直接顯示每個簇,權重最高的詞文本,而不是詞id。
- -dt:上面映射類型,由於我們是seqdictionary生成的,so。。
- -o:最終產出目錄
- -n:每個簇,只輸出20個權重最高的詞。
看看dump結果吧:
一共有20行,表示20個簇。每行形如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | VL-12722{n=1305 c=[....zorinsky's:0.011, zurich:0.006...], r=[....yuan:1.055, yugoslav:1.027,...]} Top Terms: he => 3.105303428364896 said => 2.8756448350190205 would => 2.6413800148214874 have => 2.1552908992401942 government => 1.8426488105364687 which => 1.749669294978467 economic => 1.7431561736768233 has => 1.7429241635333532 prices => 1.7182022383386604 oil => 1.673632335845538 from => 1.64287882106971 u.s => 1.6223870217115028 had => 1.602064758607711 more => 1.5874425666999086 last => 1.561653600890061 we => 1.5274837373316974 been => 1.4653439554674872 year => 1.4279387724353894 could => 1.4152588548331426 minister => 1.4146991936183066 |
其中前面的12722是簇的ID,n=1305即簇中有這麼多個文檔。c向量是簇中心點向量,格式爲 詞文本:權重(點座標),r是簇的半徑向量,格式爲 詞文本:半徑。
下面的Top Terms是簇中選取出來的特徵詞。
3、查看聚類結果
其實,聚類結果中,更重要的是,文檔被聚到了哪個類。
遺憾的是,在很多資料中,都沒有說明這一點。前文我們已經提到了,簇id -> 文檔id的結果,保存在了clusteredPoints下面。這也是mahout內置類型存儲的。我們可以用seqdumper命令查看。
| mahout seqdumper -i /user/coder4/reuters-kmeans/clusteredPoints/ |
其中,-d和-dt的原因同clusterdump。
如果不指定-o,默認輸出到屏幕,輸出結果爲形如:
| Key: 4255: Value: wt: 1.0 distance: 0.7752480913348985 vec: /reut2-000.sgm-0.txt = [14:4.670, 35:7.545, ... 11278:6.394, 11288:6.731] |
其實,這個輸出是一個SequenceFile,大家自己寫程序也可以讀出來的。
Key是ClusterID,上面clusterdump的時候,已經說了。
Value是文檔的聚類結果:wt是文檔屬於簇的概率,對於kmeans總是1.0,/reut2-000.sgm-0.txt就是文檔標誌啦,前面seqdirectionary的-nv起作用了,再後面的就是這個點的各個詞id和權重了。
三、Fuzzy-KMeans
KMeans是一種簡單有效的聚類方法,但存在一些缺點。
例如:一個點只能屬於一個簇,這種叫做硬聚類。而很多情況下,軟聚類纔是科學的。例如:《哈利波》屬於小說,也屬於電影。Fuzzy-Kmeans 通過引入“隸屬度”的方式,實現了軟聚類。
1、算法簡介
詳細的介紹轉載自:http://home.deib.polimi.it/matteucc/Clustering/tutorial_html/cmeans.html
2、工具用法
執行Fuzzy-KMeans
| mahout fkmeans -i /user/coder4/reuters-sparse/tfidf-vectors -c /user/coder4/reuters-fkmeans-clusters -o /user/coder4/reuters-fkmeans -k 20 -dm org.apache.mahout.common.distance.CosineDistanceMeasure -m 1.05 -x 200 -ow --clustering --convergenceDelta 0.01 |
新增算法的柔軟參數m,若m接近於1則接近於KMeans;隨着m增加,會有越來越多的聚簇重疊(越多的點同時屬於多個聚簇)。
3、查看隸屬度
如上文所述,在Fuzzy-KMeans中,點以一定的 “概率” 隸屬於聚簇。
我們可以用seqdumper查看隸屬度:
| mahout seqdumper -i /user/coder4/reuters-fkmeans/clusteredPoints/ |
其中的 w: xxx.xxx表示了 隸屬度,應當是 0~1之間的數。
四、Canopy
KMeans算法還有一個缺陷: k需要預先給定,在很多場景下,聚類形狀都是預先無法知道的,k更無從談起。因此,往往先用別的算法進行粗略聚類,同時確定初始值,然後再用KMeans算法。
1、算法簡介
Canopy Clustering 算法提出於2000年。優點是計算速度快,缺點是結果準確性較低。
儘管如此,其結果依然可以大致描述 聚類中心的位置。因此,常用來與KMeans算法配合使用。
(1) 將數據集向量化得到一個list後放入內存,選擇兩個距離閾值:T1和T2,其中T1 > T2,對應上圖,實線圈爲T1,虛線圈爲T2,T1和T2的值可以用交叉校驗來確定;
(2) 從list中任取一點P,用低計算成本方法快速計算點P與所有Canopy之間的距離(如果當前不存在Canopy,則把點P作爲一個Canopy),如果點P與某個Canopy距離在T1以內,則將點P加入到這個Canopy;
(3) 如果點P曾經與某個Canopy的距離在T2以內,則需要把點P從list中刪除,這一步是認爲點P此時與這個Canopy已經夠近了,因此它不可以再做其它Canopy的中心了;
(4) 重複步驟2、3,直到list爲空結束。
我再來簡單概括一下:閾值T1 > T2。到簇中心點的距離 < T2的點,必須屬於本聚簇(硬)。T2 < 到簇中心點距離 < T1的點,可以屬於多個聚簇(軟)。在後續計算可以被合併。
2、聚類用法
執行Canopy聚類
| mahout canopy -i /user/coder4/reuters-sparse/tfidf-vectors -o /user/coder4/reuters-canopy-centroids -dm org.apache.mahout.common.distance.CosineDistanceMeasure -t1 140 -t2 80 -ow |
如上所述,在距離的計算方面,我們選擇了歐式距離。閾值T1=150, t2=75。
輸出結果,也可以用ClusterDump查看。
| mahout clusterdump -i /user/coder4/reuters-canopy-centroids/clusters-0-final -d /user/coder4/reuters-sparse/dictionary.file-0 -dt sequencefile -n 20 | vim - |
這是一個粗略、大致的結果。在實際應用中,經常被用來作爲K-Means的初始聚簇中心,來代替隨機選擇的K箇中心點。這一做法有2個優點:
(1) 無需決定K,因爲我們的預設往往是不準的。
(2) 使用Canopy的聚類結果,是一個大致準確的中心點。而隨機選擇很可能陷入局部最優。
在執行k-means時,若我們不指定k,則會使用-c的路徑作爲初始聚簇中心點,並跳過隨機選擇的過程。
| mahout kmeans -i /user/coder4/reuters-sparse/tfidf-vectors -c /user/coder4/reuters-canopy-centroids/clusters-0-final -o /user/coder4/reuters-kmeans -dm org.apache.mahout.common.distance.CosineDistanceMeasure -x 200 -ow --clustering |
3、參數選擇
最後,我們討論以下Canopy的參數T1和T2。
- T1 > T2,具體值是文檔及距離計算公式而定。
- 若T1過大,會使得許多點屬於多個Canopy,造成各個簇的中心點距離比較近,使得簇之間的區分不明顯。
- 若T2過大,強標記數據點的數量會增加,從而減少簇個數。
- 若T2過小,會增加簇的個數,以及計算時間。
網上有人給出了這個做法,僅供參考:
- 對數據進行採樣。
- 計算所有文檔之間的平均距離(使用要在Canopy中用的距離公式)。
- T1 = 平均距離 * 2;T2 = 平均距離。
上述做法有一定道理,但我認爲,以下更加合理:
- 對數據進行採樣。
- 選擇一個T2,T1 = 2 * T1。
- 進行聚類,並評測聚類效果,可使用k-fold交叉驗證。
- 迭代選擇下一個T2。
- 直到找到最優的T1 T2。
五、Spectral
1、譜聚類算法簡介
譜聚類算法,參考了文章《Mahout Spectral聚類》。
譜聚類算法是一種較爲現代的圖聚類算法。與K-Means等傳統聚類相比,它具有以下特點:
- 可以對非歐式距離空間的點進行聚類。傳統K-Means將點視爲向量,並計算距離。而譜聚類算法要求直接給出兩樣本間相似度的矩陣。使得一些不便於在歐式空間計算的多特徵聚類問題,有了更好的解法。(例如,性別,年齡2個特徵,在歐式空間中就沒有顯著意義)。
- 上面的這一更寬泛的約束條件,使得譜聚類對樣本空間的形狀無限制,並能收斂於全局最優解(無需使用)。
一種典型的譜聚類算法的大致流程是:
- 構建樣本集的相似度矩陣W。
- 對相似度矩陣W進行稀疏化,形成新的相似度矩陣A。
- 構建相似度矩陣A的拉普拉斯矩陣L。
- 計算拉普拉斯矩陣L的前k個特徵值與特徵向量,構建特徵向量空間。
- 將前k個特徵向量(列向量)組合成N*k的矩陣,每一行看成k維空間的一個向量,利用K-means或其它經典聚類算法對該矩陣進行聚類。
其中,轉化爲拉普拉斯矩陣實際是一個降維的過程。正是這一特點,使得譜聚類能夠處理超大規模的數據。
2、Mahout中的譜聚類
上文已經提到:
- 傳統K-Means等聚類中,需要將每個樣本轉化爲一個向量。
- 譜聚類中,則需要直接給一個矩陣,其中存儲了任意兩個樣本之間的相似度。
例如:
在實際應用中,相似矩陣(affinity matrix)是相當稀疏的。所以,Mahout採用了鄰接矩陣的輸入格式,即(i, j, affinity)表示第i個樣本與第j個樣本的相似度是affinity。
同時,還需要輸入矩陣的維度。原因應該是很好理解的。
如上圖中的數據,轉化完畢後,就是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 0,0,0 0,1,0.6 0,2,0.9 0,3,0.1 0,4,0 0,5,0 1,0,0.6 1,1,0 1,2,0.8 1,3,0 1,4,0 1,5,0 2,0,0.9 2,1,0.8 2,2,0 2,3,0 2,4,0 2,5,0.2 3,0,0.1 3,1,0 3,2,0 3,3,0 3,4,0.7 3,5,0.9 4,0,0 4,1,0 4,2,0 4,3,0.7 4,4,0 4,5,0.8 5,0,0 5,1,0 5,2,0.2 5,3,0.9 5,4,0.8 5,5,0 |
Mahout中,將譜聚類與KMeans進行了整合,執行命令:
| mahout spectralkmeans -i /user/coder4/sc-data -o /user/coder4/sc-spectral -d 6 -k 2 -x 100 |
參數說明:
- -i :輸入的相似度矩陣,鄰接矩陣。
- -k:目標聚成2個簇。
- -o:聚簇中間結果。
- -d:相似度矩陣維度爲6,也即樣本共6個。
- -x:100,最多迭代100次。
- -cd:收斂閾值,默認0.5
其他可選參數:
- -ssvd:使用svd矩陣分解降維。
- -q:svd相關。
輸出的目錄結構,與K-Means等相似:
| /user/coder4/sc-spectral/clusters-0/part-eigenSeed /user/coder4/sc-spectral/kmeans_out/_policy /user/coder4/sc-spectral/kmeans_out/clusteredPoints /user/coder4/sc-spectral/kmeans_out/clusters-0 /user/coder4/sc-spectral/kmeans_out/clusters-1-final |
說明一下:
- sc-spectral/clusters-0:初始聚簇。
- sc-spectral/kmeans_out/clusteredPoints:最終結果,樣本->聚簇映射。
- sc-spectral/kmeans_out/clusters-1-final:最終聚簇的信息。
先看一下聚簇映射:
| mahout seqdumper -i /user/coder4/sc-spectral/kmeans_out/clusteredPoints # Output Key: 1: Value: wt: 1.0 distance: 0.48931489242582005 vec: 0 = [0.188, -0.982] Key: 1: Value: wt: 1.0 distance: 0.7493112387139778 vec: 1 = [0.915, 0.404] Key: 0: Value: wt: 1.0 distance: 0.04922584424967602 vec: 2 = [-0.902, 0.432] Key: 1: Value: wt: 1.0 distance: 0.2811018866117967 vec: 3 = [0.465, -0.885] Key: 1: Value: wt: 1.0 distance: 1.1021255831766634 vec: 4 = [0.748, 0.664] Key: 0: Value: wt: 1.0 distance: 0.012306461062418617 vec: 5 = [-0.994, 0.112] Count: 6 |
如上所示,這個順序,是按照輸入樣本順序來的。Key 1表示屬於第2個簇,0表示第1個簇。distance是點與簇的相似距離。
然後來看一下簇中心:
| mahout clusterdump -i /user/coder4/sc-spectral/kmeans_out/clusters-1-final |
輸出結果:
| VL-0{n=3 c=[-0.963, 0.219] r=[0.043, 0.151]} Weight : [props - optional]: Point: 1.0 : [distance=0.04922584424967602]: 2 = [-0.902, 0.432] 1.0 : [distance=0.012306461062418617]: 5 = [-0.994, 0.112] VL-1{n=5 c=[0.501, -0.356] r=[0.293, 0.732]} Weight : [props - optional]: Point: 1.0 : [distance=0.48931489242582005]: 0 = [0.188, -0.982] 1.0 : [distance=0.7493112387139778]: 1 = [0.915, 0.404] 1.0 : [distance=0.2811018866117967]: 3 = [0.465, -0.885] 1.0 : [distance=1.1021255831766634]: 4 = [0.748, 0.664] |
於 K-Means一樣,VL-XX是簇名稱,n代表簇中含有幾個元素。c是簇中心,r是簇半徑。
然而奇怪的是,我們可以發現,上面的n都是錯的,而下面簇中點的打印是對的不知道是什麼Bug…
六、LDA
LDA是一種主題模型,它是一種考慮了詞貢獻的,較爲高級的“聚類”算法,主要功能爲:
- 給定主題數k,輸出文檔屬於每個主題的概率(越大表示越貼近該主題)。
- 輸出每個主題中,權重最大的幾個詞。相當於傳統聚類之後的Tag。
關於算法、原理方面,本文就不做過多的介紹了,感興趣的可以查看相關論文。
考慮到LDA的特性,提取特徵的時候,我們需要使用tf而非tfidf:
| mahout seq2sparse -i /user/coder4/reuters-seq -o /user/coder4/reuters-sparse -ow --weight tf --maxDFPercent 50 --namedVector |
Mahout實現的LDA有個大坑:tf的vector,詞必須是Ingeter類型,即要我們把word轉換成wordid。
| mahout rowid -i /user/coder4/reuters-sparse/tf-vectors -o /user/coder4/reuters-cvb-vectoers |
生成的有2個子目錄,我們只用下面這個matrix:
| hadoop dfs -ls /user/coder4/reuters-cvb-vectoers Found 2 items /user/coder4/reuters-cvb-vectoers/docIndex /user/coder4/reuters-cvb-vectoers/matrix |
LDA訓練:
| mahout cvb -i /user/coder4/reuters-cvb-vectoers/matrix -dict /user/coder4/reuters-sparse/dictionary.file-0 -dt /user/coder4/reuters-lda-documents -o /user/coder4/reuters-lda -k 20 -x 100 -ow -nt 41807 |
上述參數,說明一下:
- -k 主題數20
- -dt:輸出的?
- -o:輸出的?
- -x:迭代100次,其實對於LDA,1000~2000次是比較合理的。
- -nt:詞的數量,即dictionary.file-0的大小。
PS:Mahout這個LDA,執行效率真心不高,也可能是我的數據太小,機器太少。
文檔->主題的概率
| mahout seqdumper -i /user/coder4/reuters-lda-documents |
輸出共21578行,代表了文檔集合中的所有文檔。
- Key是文檔id,與文件的對應關係可以在/user/coder4/reuters-cvb-vectoers/docIndex中查看。
- Value是文檔屬於Topic 0~19的概率。按照值Sort一下,就能知道文檔屬於哪個主題的概率最大。
| Key: 0: Value: {0:6.598480107368694E-4,1:0.0011146789596809571,2:0.031866546260962164,3:3.0247890790462996E-4,4:0.03744780092635172,5:0.0013729445191034027,6:0.15611424913721567,7:0.0012755723292771565,8:5.7202115335459274E-5,9:7.1215044519594E-4,10:5.743926686503027E-4,11:0.0031917247557773252,12:0.6581022112710254,13:0.00817715737882251,14:3.1885030061811875E-4,15:0.011053824003897846,16:0.031248628641714408,17:0.03558264264919826,18:0.01996534695313223,19:8.617497653994247E-4} |
主題->詞的概率
| mahout seqdumper -i /user/coder4/reuters-lda |
- 一共有20行有效輸出,Key 0~19,代表了20個主題。
- 每個Value中有41806個詞的權重。表示了詞屬於當前主題的權重。
本來有個LDAPrintTopics,可以直接打印Topic對應的詞的,但是年久失修,已經不能用在新版的cvb的LDA上了。大家可以寫程序對上免每個Topic中詞的權重進行排序,從而獲得每個主題的代表詞。