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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容