到目前为止,github上的LightLDA还没有出比较详尽的文档,所以我在使用前进行了一番摸索。本文主要是对LightLDA单机版使用的一些简单说明,包括输入输出的格式说明,参数说明和自己实现的java版本的输入输出接口。
输入
输入数据需要放在一个文件夹下,输入需要先把输入数据转化为libsvm格式,再由LightLDA提供的独立的dump_binary
工具将libsvm格式转化为可用的格式。example目录下有text2libsvm.py文件,可以将UCI文件转化为libsvm文件。
UCI文件格式见链接不再赘述。
D
W
NNZ
docID wordID count
docID wordID count
...
docID wordID count
libsvm格式:两个文件 libsvm和 dict
libsvm:
文档号\t词id1:该词在文档中出现次数 词id2:次数 ...
文档号从1开始代指某篇文档
词id以0开始,与dict对应
次数为文档号对应的文档中该词出现的次数不是总次数
dict:
词id\t对应词\t出现总数\n
出现总数是所有文档出现总数
我写了一个可以将分词后的结果转换为非严格UCI格式的工具,在工具:text2UCI,可供参考。
可以遵循 text -> UCI -> libsvm -> dump这样的步骤得到lightLDA的输入文件。或者直接生成libsvm格式,再dump。dump_binary这一步是不可少的,是lightLDA为了提升性能转化为其自定义的文件格式。
dump_binary用法
dump_binary <libsvm_input> <word_dict_file_input> <binary_output_dir> <output_file_offset>
训练参数
void Config::PrintTrainingUsage()
{
printf("LightLDA usage: \n");
printf("-num_vocabs <arg> Size of dataset vocabulary \n");
printf("-num_topics <arg> Number of topics. Default: 100\n");
printf("-num_iterations <arg> Number of iteratioins. Default: 100\n");
printf("-mh_steps <arg> Metropolis-hasting steps. Default: 2\n");
printf("-alpha <arg> Dirichlet prior alpha. Default: 0.1\n");
printf("-beta <arg> Dirichlet prior beta. Default: 0.01\n\n");
printf("-num_blocks <arg> Number of blocks in disk. Default: 1\n");
printf("-max_num_document <arg> Max number of document in a data block \n");
printf("-input_dir <arg> Directory of input data, containing\n");
printf(" files generated by dump_block \n\n");
printf("-num_servers <arg> Number of servers. Default: 1\n");
printf("-num_local_workers <arg> Number of local training threads. Default: 4\n");
printf("-num_aggregator <arg> Number of local aggregation threads. Default: 1\n");
printf("-server_file <arg> Server endpoint file. Used by MPI-free version\n");
printf("-warm_start Warm start \n");
printf("-out_of_core Use out of core computing \n\n");
printf("-data_capacity <arg> Memory pool size(MB) for data storage, \n");
printf(" should larger than the any data block\n");
printf("-model_capacity <arg> Memory pool size(MB) for local model cache\n");
printf("-alias_capacity <arg> Memory pool size(MB) for alias table \n");
printf("-delta_capacity <arg> Memory pool size(MB) for local delta cache\n");
exit(0);
}
说明
-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相对会小很多。
例子
$bin/lightlda -num_vocabs 111400 -num_topics 1000 -num_iterations 100 -alpha 0.1 -beta 0.01 -mh_steps 2 -num_local_workers 1 -num_blocks 1 -max_num_document 300000 -input_dir $dir -data_capacity 800
输出结果
每轮训练时间会随着迭代次数增加而减少,本地实验中,153W+个词汇,14W+篇文档,共耗时4h。输出结果主要是4个文件
- doc_topic.blockID 这个blockID下的doc_topic分布,格式: 文档id 主题id:次数
- server_0_table_0.model word_topic分布,格式:词id 主题id:次数
- server_0_table_1.model 只有一行,所有主题的出现次数统计, 主题id:次数
- log文件
输出给出了每个词的主题次数分布和每篇文档的主题次数分布,没有给出文档-主题的概率分布和主题-词的概率分布。但是根据这个结果已经可以得到概率分布,需要自己写一个接口,进行频数统计。
如果是来了一篇新文档,可以利用已知的词分布,也可以通过采样得到新文档的主题分布。也可以通过lightLDA的对新文档的接口infer方法,得到转化结果。
我写了个转化接口,可以让结果看起来更直观一点,lightLDA输出接口-java版本。
网友评论