短文本的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需要升级。

#1.gcc版本检查 需要先确认
yum install gcc gcc-c++ 
 gcc --version 4.4.7 #gcc的版本要求是gcc-4.8.5:

#2.gcc编译安装
wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.5/gcc-4.8.5.tar.gz
#编译安装 GCC 需要依赖 mpc,mpfr,gmp包。好在 GCC 源码里自带脚本可以轻松下载依赖包
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 
../configure --prefix=/usr --enable-checking=release --enable-languages=c,c++ --disable-multilib
make –j4 && make install

参数说明:
<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的,及其特殊情况下会冲突

#gcc 冲突解决 
 which gcc  #如果显示的是/usr/bin/gcc 
 mv /usr/bin/gcc /usr/bin/gcc4.4.7 
 ln -s /usr/local/bin/gcc(新gcc) /usr/bin/gcc 

# g++冲突解决 
 mv /usr/bin/g++ /usr/bin/g++4.4.7 
 ln -s /usr/local/bin/g++(新) /usr/bin/g++

# cc 冲突解决 
 mv /usr/bin/cc /usr/bin/cc4.4.7 
 ln -s /usr/local/bin/cc(新) /usr/bin/cc

#c++冲突解决 
 mv /usr/bin/c++ /usr/bin/c++4.4.7 
 ln -s /usr/local/bin/c++(新) /usr/bin/c++

二。git安装

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

三、LightLDA源码安装

cd /usr/local/src 
 git clone https://github.com/Microsoft/lightlda #如果报ssl error可能是ssl版本低,升级yum update nss 
 cd lightlda

安装
默认安装sh ./build.sh会报错,里面的一些地址已经更换,按照以下的顺序安装:

1.下载DMTK,微软开源的机器学习工具包,lightLDA是基于DMTK的

yum install libopenmpi-dev openmpi-bin build-essential cmake git 
 git clone -b multiverso-initial https://github.com/Microsoft/multiverso.git 
 cd multiverso

2.安装第三方组件:

cd third_party

默认运行sh ./install.sh会失败的

2.1 安装 zeromq

注意一点:需要将zeromq的lib路径加入到/etc/ld.so.conf 后再编译,否则在后面运行的时候报错:

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

vi /etc/ld.so.conf 
#加入 /usr/local/src/lightlda/multiverso/third_party/lib ldconfig 
# 注意这个时候会报错ldconfig: /usr/lib64/libstdc++.so.6.0.19-gdb.py 不是 ELF 文件 - 它起始的魔数错误 
 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 
#如果失败,自行下载到本地上传到third_party 
 tar -zxf zeromq-4.1.3.tar.gz cd zeromq-4.1.3 
 ./configure --prefix=/usr/local/src/lightlda/multiverso/third_party --without-libsodium 
 make -j4 
 make install -j4 
 cd .. 
 rm -rf zeromq-4.1.3

2.2 Get the C++ Wrapper zmq.hpp

wget https://github.com/zeromq/cppzmq/blob/master/zmq.hpp 
# 不能直接wget会乱码,下载整个cppzmq的项目,解压出来zmp.hpp后单独上传 
 mv zmq.hpp /usr/local/src/lightlda/multiverso/third_party/include/

2.3 Get MPICH2

wget http://www.mpich.org/static/downloads/3.0.4/mpich-3.0.4.tar.gz 
# wget或者单独下载后上传 
 tar -zxf mpich-3.0.4.tar.gz cd mpich-3.0.4 
 ./configure --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

至此,已经完成第三方组件的编译安装

3.编译安装zmtk和lightlda

3.1 编译安装DMTK

cd ../
make -j4 all

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.gz
wget https://archive.ics.uci.edu/ml/machine-learning-databases/bag-of-words/vocab.nytimes.txt

2.安装使用

(1)解压后的txt文件是UCI格式的文件,格式如下(其中前三行统计数据可以没有)

文档数
单词数
NNZ
docID wordID count
docID 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 mytest 
head -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的

修改print
os[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秒左右可出结果

    原文作者:jimmy wong
    原文地址: https://zhuanlan.zhihu.com/p/64325973
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞