短文本的LDA模型實現及應用(二)

在主題模型的構建中,如果訓練集較小,效果通常不會太理想(對監督學習),但是大數據量語料分析,常規方式性能堪憂,微軟開源的LightLDA在性能上有了很大的提升。詳見

http://www.flickering.cn/uncategorized/2016/05/peacock%E9%87%87%E6%A0%B7%E7%AE%97%E6%B3%95%E6%80%A7%E8%83%BD%E6%AF%94%E8%BE%83/


對比sparkLDA和JGibbsLDA,前者不支持Gibbs採樣,還是用的EM和差分推理。後者是一個需要用命令行運行的工程,應該可以整合到spark,但是基於對lightLDA高性能口碑的好奇和興趣,以及假如要使用lda模型,大型語料上的運行性能還是很重要的。

一、升級gcc版本

centos7的gcc滿足4.8.5的版本要求,但是centos6需要升級。

<code> 

yum

install gcc gcc-c++

gcc

--version 4.4.7 #gcc的版本要求是gcc-4.8.5:

wget

https://ftp.gnu.org/gnu/gcc/gcc-4.8.5/gcc-4.8.5.tar.gz

tar

czxf gcc-4.8.5.tar.gz

cd

gcc-4.8.5

./contrib/download_prerequisites

mkdir

gcc-build-4.8.5

cd

gcc-build-4.8.5

--prefix=/usr --enable-checking=release --enable-languages=c,c++ --disable-multilib

make

–j4 && make install

/<code>

參數說明:
<1>--prefix 為了避免安裝後系統裡出現多個版本的 GCC,這裡直接將編譯安裝的目錄指定為 /usr,如果不指定–prefix,則會默認安裝到 /usr/local 下
<2>--enable-languages //指定 gcc 能編譯哪些語言的文件,每種語言用逗號分隔, 例如 c,c++,java
<3>--disable-multilib //默認gcc 能在32位系統上將代碼編譯成64位程序,或者在64位系統上編譯成32位程序,

完成後, 默認會替換為正確的4.8.5的,及其特殊情況下會衝突

<code> 
 

which

gcc #如果顯示的是/usr/bin/gcc

mv

/usr/bin/gcc /usr/bin/gcc4.4.7

ln

-s /usr/local/bin/gcc(新gcc) /usr/bin/gcc

mv

/usr/bin/g++ /usr/bin/g++4.4.7

ln

-s /usr/local/bin/g++(新) /usr/bin/g++

mv

/usr/bin/cc /usr/bin/cc4.4.7

ln

-s /usr/local/bin/cc(新) /usr/bin/cc

mv

/usr/bin/c++ /usr/bin/c++4.4.7

ln

-s /usr/local/bin/c++(新) /usr/bin/c++

/<code>

二。git安裝

<code>

yum

install curl-devel expat-devel gettext-devel openssl-devel zlib-devel

yum

install gcc perl-ExtUtils-MakeMaker

yum

remove git

cd

/usr/local/src

wget

https://www.kernel.org/pub/software/scm/git/git-2.0.5.tar.gz --no-check-certificate

tar

xzf git-2.0.5.tar.gz

cd

git-2.0.5

make

prefix=/usr/local/git all

make

prefix=/usr/local/git install

echo

"export PATH=$PATH:/usr/local/git/bin" >> /etc/bashrc

source

/etc/bashrc

git

--version

/<code>

三、LightLDA源碼安裝

<code>

cd

/usr/

local

/src git

clone

https://github.com/Microsoft/lightlda

cd

lightlda/<code>

安裝默認安裝sh ./build.sh會報錯,裡面的一些地址已經更換,按照以下的順序安裝:

1.下載DMTK,微軟開源的機器學習工具包,lightLDA是基於DMTK的

<code>yum 

install

libopenmpi-dev openmpi-

bin

build

-essential cmake git git

clone

-b multiverso-

initial

https://github.com/Microsoft/multiverso.git cd multiverso/<code>

2.安裝第三方組件:
cd third_party
默認運行sh ./install.sh會失敗的
2.1 安裝 zeromq
注意一點:需要將zeromq的lib路徑加入到/etc/ld.so.conf 後再編譯,否則在後面運行的時候報錯:

<code> : 

error while loading shared libraries: libzmq.so.5: cannot open shared object file: No such file or directory

vi

/etc/ld.so.conf

mv

/usr/lib64/libstdc++.so.6.0.19-gdb.py /usr/lib64/bak_libstdc++.so.6.0.19-gdb.py #後重新執行ldconfig

wget

https://archive.org/download/zeromq_4.1.3/zeromq-4.1.3.tar.gz

tar

-zxf zeromq-4.1.3.tar.gz cd zeromq-4.1.3

--prefix=/usr/local/src/lightlda/multiverso/third_party --without-libsodium

make

-j4

make

install -j4

cd

..

rm

-rf zeromq-4.1.3

/<code>

2.2 Get the C++ Wrapper zmq.hpp

<code>wget 

https:

/

/github.com/zeromq

/cppzmq/blob

/master/zmq

.hpp mv zmq.hpp /usr/local/src/lightlda/multiverso/third_party/

include

//<code>

2.3 Get MPICH2

<code>

wget

http://www.mpich.org/static/downloads/3.0.4/mpich-3.0.4.tar.gz

tar

-zxf mpich-3.0.4.tar.gz cd mpich-3.0.4

--prefix=/usr/local/src/lightlda/multiverso/third_party --disable-fc --disable-f77

make

-j4

make

install -j4

cd

..

rm

-rf mpich-3.0.4/

rm

-rf *.tar.gz

/<code>

至此,已經完成第三方組件的編譯安裝

3.編譯安裝zmtk和lightlda

3.1 編譯安裝DMTK

<code>

cd

../

make

-j4 all

/<code>

3.2 編譯安裝lightLDA

cd .. make -j4

至此,在lightLDA的bin目錄下已經有lightlda和其他工具了

四、說明

Smultiverso(DMTK):是一個標準c++lib庫,是一個基於框架的參數服務器,用來在多臺機器上訓練大數據的機器學習模型,提供了友好的api接口,使用者不必考慮分佈式模型存儲和操作,內部線程和內部進程間的交互,多線程的管理,只需要專注於機器學習的邏輯:數據,模型和訓練。

Libzmq:zeroMq輕量級的消息內核繼承了標準的socket接口,具有定製化消息中間件產品的特點,zeroMQ socke提供了異步消息隊列,多消息模式,消息過濾的抽象,無縫對接多種傳輸協議。

mpich-3.0.4:是一個高性能便攜式Message Passing Interface標準的實現,將線程的管理和交互分離。

五、實例文檔的安裝使用

1.下載示例文檔

wget https://archive.ics.uci.edu/ml/machine-learning-databases/bag-of-words/docword.nytimes.txt.gzwget https://archive.ics.uci.edu/ml/machine-learning-databases/bag-of-words/vocab.nytimes.txt

2.安裝使用 (1)解壓後的txt文件是UCI格式的文件,格式如下(其中前三行統計數據可以沒有)

文檔數單詞數NNZdocID wordID countdocID wordID count

(2)需要使用example中的text2libsvm將UCI格式轉化為libsvm,默認腳本是python2的,在python3下如要修改如下:

print使用print()替代#if not word_dict.has_key(word_id):用if word_id not in word_dict:替代

(3)用bin/dump_binary將libsvm轉化為二進制的lightLDA格式數據

(4)示例的doc文件是6000W的數據,可以用head -n 100000 docword.nytimes.txt > docword.nytimes_new.txt 提取10w數據測試

(5)完整的執行過程如下:

cd /usr/local/src/lightlda/ mkdir mytest cd mytest cp ../example/text2libscm.py ./ vi text2libscm.py #修正代碼 mkdir output

#輸出output的libsvm和字典文件python ./text2libsvm.py ./docword.nytimes.txt ./vocab.nytimes.txt output/nytimes.libsvm
output/nytimes.word_id.dict

#輸出block文件和vocab../bin/dump_binary output/nytimes.libsvm
output/nytimes.word_id.dict output 0

#運行lightLDA ../bin/lightlda -num_vocabs 18000 -num_topics 10 -num_iterations 100 -alpha 2 -beta 0.1 -mh_steps 2 -num_local_workers 1 -num_blocks 1 -max_num_document 500 -input_dir output -data_capacity 2

3.lightlda參數說明:

-num_vocabs 數據集中包含的單詞數目,是詞彙表中的詞的數目,可以比實際值偏大 -num_topics 要訓練的主題數目,經驗值是sqrt(#docs)/3,可以用HDP或交叉驗證確定 -num_iterations 迭代次數,越多越好 -alpha 對稱Dirichlet分佈的參數alpha,經驗值設置為 50/#topics -beta 對稱Dirichlet分佈的參數beta, 經驗值設置為0.1 -max_num_document 訓練的文檔數目 -input_dir 訓練數據所在目錄,目錄下需有轉化為lightlda自定義的輸入格式文件 -data_capacity 至少要最大的block文件的size,block文件是由dump_binary生成的。 -model/alias/delta capacity 可以指定任意值,一般model/alias大小是同義數量級,delta相對會小很多。

4. 輸出結果 結果數據直接在mytest目錄:一共4個文件

doc_topic.0 #doc_topic.blockID 這個blockID下的doc_topic分佈,格式: 文檔id 主題id:次數 server_0_table_0.model #word_topic分佈,格式:詞id 主題id:次數server_0_table_1.model #只有一行,所有主題的出現次數統計, 主題id:次數 LightLDA.40000.log #日誌文件


六、分佈式運行過程

lightlda的真正能力在於分佈式的執行,可以在多臺機器上同步線性擴展,以下例子在2臺阿里雲8GBECS上測試

1.以50W數據測試 (以下內容在server1上運行)

cd mytesthead -n 500000 docword.nytimes_ori.txt > docword.nytimes.txt #截取50W測試數據#轉換成libsvm格式 python ./text2libsvm.py ./docword.nytimes.txt ./vocab.nytimes.txt output/nytimes.libsvm
output/nytimes.word_id.dict

2.數據預處理,將libsvm切分為幾部分,使用phraug(1)分割為2份數據 #在mytest目錄下

git clone https://github.com/zygmuntz/phraug.git

#因為腳本是python2的,將chunk.py修改為版本3的

修改printos[n].write( line)修改為os[n].write( line.encode('utf-8') )

#因為測試環境2臺機器,將數據分割為2份:

cd output/ python ../phraug/chunk.py ./nytimes.libsvm 2 #結果生成nytimes_0.libsvm 和nytimes_1.libsvm

(2)轉換格式為2進制的lightLDA格式

cd ../ ../bin/dump_binary output/nytimes_0.libsvm
output/nytimes.word_id.dict output 0 ../bin/dump_binary output/nytimes_1.libsvm
output/nytimes.word_id.dict output 1#在output下生成如下的文件 block.0 clock.1 vocab.0 vocab.1 vocab.0.txt vocab.1.txt nytimes_0.libsvm nytimes_1.libsvm

(3)將1的文件放置到server2的指定目錄下,同時修改為0(4)在server2重命名1的文件: 注意:每個文件夾下是5個文件(5)配置兩臺機器的無密碼訪問

cd ~/.ssh #看看裡面有沒有id_rsa,如果沒有需要生成秘鑰 ssh-keygen -t rsa ssh-copy-id root@遠端IP #兩臺機器分別執行 ssh-copy-id root@自己IP #否則報錯Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)

(6)在其中一臺機器上執行


/usr/local/src/lightlda/mytest #創建機器列表文件machinelist vi machinelist 47.95.237.1 60.205.1.2

#將mpi的路徑加入到系統環境中vi /etc/profile PATH=$PATH:$
HOME/bin:/usr/local/src/lightlda/multiverso/third_party/bin export LD_LIBRARY_PATH=
/usr/local/src/lightlda/multiverso/third_party/lib source /etc/profile

#分佈式執行:注意開啟動態端口的防火牆 /etc/hosts的主機名和ip一定對應

(7)執行

cd /usr/local/src/lightlda/mytest mpiexec -machinefile ./machinelist ../bin/lightlda -num_vocabs 18000 -num_topics 10 -num_iterations 100 -alpha 2 -beta 0.1 -mh_steps 2 -num_local_workers 1 -num_blocks 1 -max_num_document 500 -input_dir output -data_capacity 2

(8)問題:*** Error in `../bin/lightlda': munmap_chunk(): invalid pointer: 0x0000000008b778f0 ***

測試50W數據在8G的ecs上報錯,30w測試通過,多輪測試發現是內存限制(50W單機也無法運行),注意不同的數據集調整-num_vocabs等參數

(9)補充偶然發現,lightLDA的python實現

https://github.com/nzw0301/lightLDA


六、其他

實際測試,單臺8GB機器最多運行數據30W左右,50W就報內存錯誤,看來對內存的依賴較大 lightlda對多文檔的主題模型分析非常有效,性能也非常好,2臺機器70W左右再10秒左右可出結果


分享到:


相關文章: