短文本的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秒左右可出结果


分享到:


相關文章: