使用 JGibbLDA 进行 LDA 模型训练及主题分布预测
最近新闻个性化推荐项目中用到 LDA 来确定各个新闻的主题分布,我优先使用了 Spark Mllib LDA,发现并不理想,主要表现在极吃内存且计算慢,所以打算暂时放弃之。优先使用 Spark LDA 的主要原因是希望和能和 Spark Streaming 结合在一起进行实时预测。所以在考察新方案时优先考虑 Java 实现的 LDA 开源版本,之后发现了 JGibbLDA,下面从使用角度进行简单介绍
JGibbLDA 是一个由 Java 语言实现的 LDA 库,使用吉布斯采样进行参数估计和推断
在命令行中训练 JGibbLDA 模型
本节,将介绍如何使用该工具。假设当前工作目录是在 JGibbLDA 根目录并且我们使用的是 linux,命令行如下:
java [-mx512M] -cp bin:lib/args4j-2.0.6.jar jgibblda.LDA -est [-alpha <double>] [-beta <double>] [-ntopics <int>] [-niters <int>] [-savestep <int>] [-twords <int>] –dir <string> -dfile <string>
各参数含义:
-
-est
:从头开始推断 LDA 模型 -
-alpha <double>
:alpha 的值,LDA 的超参数。默认值为50/K
(K 是 topics 个数) -
-beta <double>
:beta 的值,同样是 LDA 的超参数。默认值为 0.1 -
-ntopics <int>
:topics 个数。默认值为100,需要根据输入数据集来定 -
-niters <int>
:吉布斯采样迭代次数。默认值为 2000 -
-savestep <int>
:LDA 模型在哪一步(以吉布斯采样迭代为单位)保存到磁盘。默认值为200 -
-twords <int>
:每个 topic 最匹配的词个数。默认值为0。如果将该值设为大于0,比如 20,JGibbLDA 将在每次将模型保存到磁盘的时候都会打印出每个 topic 最匹配的 20 个词 -
-dir <string>
:训练数据文件所在目录 -
-dfile <string>
:训练数据文件名
数据格式
训练数据和待预测数据具有相同的格式,如下:
[M]
[document1]
[document2]
...
[documentM]
第一行 [M]
是指总文档数,在此之后的每一行都是一个文档。[documenti]
是数据集第 i 个文档且由 Ni
个词组成:
[documenti] = [word-i1] [word-i2] ... [wordi-Ni]
所有的 [Word-ij](i=1..M, j=1..Ni)
都是词并由空格隔开(这里不要求每行的词个数一致,根据对应文档的正式情况填写即可)
注意:这里的每行的词都应该是提取出来的(比如利用分词库提取)
输出
使用 JGibbLDA 进行吉布斯采样 LDA 推荐会输出以下五个文件:
<model_name>.others
<model_name>.phi
<model_name>.theta
<model_name>.tassign
<model_name>.twords
其中:
-
<model_name>
:LDA 模型的名字,对应于模型被保存在硬盘上的时间步骤。举例来说,在吉布斯采样第 400 次迭代的时候保存到磁盘的模型的名字为model-00400
,第 1200 次采样的名字为model-01200
,最后一次迭代对应的模型名字为model-final
-
<model_name>.others
:该文件训练 LDA 模型的各个参数,比如:
alpha=?
beta=?
ntopics=? # i.e., number of topics
ndocs=? # i.e., number of documents
nwords=? # i.e., the vocabulary size
liter=? # i.e., the Gibbs sampling iteration at which the model was saved
-
<model_name>.phi
:该文件包含 “词-主题” 分布,每行是一个 topic,每列是词汇表中的一个词 -
<model_name>.theta
:该文件包含 “主题-文档” 分布,每行是一个文档,每列是一个主题 -
<model_name>.tassign
:该文件包含训练数据中的词对应的主题,每行代表一个文档,由一组<word-ij>:<word-ij的 topic>
组成 -
<model_file>.twords
:包含每个 topic 最匹配的词,词个数在命令行参数中指定
JGibbLDA 还保存一个叫做 wordmap.txt,该文件保存了词及其对应的 id(整形)
案例
举例,我们希望以 models/casestudy/newdocs.dat
为训练数据推断出一个 LDA 模型,然后用该模型推断存储在 models/casestudy/newdocs.dat
中的文档的主题分布
设置主题数为100,alpha = 0.5 且 beta = 0.1,迭代 1000 次,每迭代 100 次保存一次模型至磁盘,每次保存模型时打印出与各个 topic 最相关的 20 个词。假设我们现在处于 JGibbLDA 的根目录,那么我们将执行以下命令:
java -mx512M -cp bin:lib/args4j-2.0.6.jar jgibblda.LDA -est -alpha 0.5 -beta 0.1 -ntopics 100 -niters 1000 -savestep 100 -twords 20 -dfile models/casestudy/newdocs.dat
训练完之后,在目录 models/casestudy
,我们可以看到上文中描述的 5 个输出文件
现在,我们需要在上一步 1000 次迭代之后再执行 800 次迭代,并设置每 100 次迭代保存一次模型,每次保存模型时打印出各个 topic 最相关的 30 个词,那么我们将执行下面的命令行:
java -mx512M -cp bin:lib/args4j-2.0.6.jar -estc -dir models/casestudy/ -model model-01000 -niters 800 -savestep 100 -twords 30
接下来,我们需要使用上一步训练出的模型对 newdocs.dat
(该文件存储在模型相同目录) 中的文档进行主题分布预测,我们可以使用这样的命令:
java -mx512M -cp bin:lib/args4j-2.0.6.jar -inf -dir models/casestudy/ -model model-01800 -niters 30 -twords 20 -dfile newdocs.dat
编码预测文档主题分布
初始化推断器
为了在一个未知的数据集上推断出一个 LDA 主题模型,我们首先需要一个推断器。由于加载一个模型的耗时较长,我们通常初始化一个推断器并在多次推断中使用。首先,我们需要创建一个 LDACmdOption
实例,并类似下面这样进行初始化:
LDACmdOption ldaOption = new LDACmdOption();
ldaOption.inf = true;
ldaOption.dir = "C:\LDAModelDir";
ldaOption.modelName = "newdocs";
ldaOption.niters = 100;
其中,LDACmdOption
的 dir
成员是包含模型(比如:通过命令行训练而来)的目录;成员 modelName
是模型名;niters
表示在第几次迭代保存的模型。接下来,我们使用 ldaOption
来初始化推断器:
Inferencer inferencer = new Inferencer();
inferencer.init(option);
预测未知数据
- 预测文件中的数据
ldaOption.dfile = "input-lda-data.txt";
Model newModel = inferencer.inference();
其中,dfile
对应的文件格式与训练数据一致
- 预测一个字符串数组
String [] test = {"politics bill clinton", "law court", "football match"};
Model newModel = inferencer.inference(test);
- 2016广东工业大学新生杯决赛网络同步赛暨全国新生邀请赛 题解&源码
- 深入浅出MongoDB复制
- Selenium2+python自动化34-获取输入框联想词
- 分解质因子(个人模版)
- 高斯混合聚类(GMM)及代码实现
- 预处理素数(个人模版)
- Cnm%(个人模版)
- Selenium2+python自动化33-文件上传(send_keys)
- hive的partition的作用和使用方法
- 线段树,最大值查询位子(个人模版)
- set使用实例1+lower_bound(val)(个人模版)
- Selenium2+python自动化29-js处理多窗口
- 谷歌「机弦」有何玄机?
- 01字典树贪心查询+建立+删除(个人模版)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 练习7-10 查找指定字符
- 浙大版《C语言程序设计(第3版)》题目集 练习7-11 字符串逆序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-1 选择法排序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-2 求一批整数中出现最多的个位数字
- 浙大版《C语言程序设计(第3版)》题目集 习题7-3 判断上三角矩阵
- 浙大版《C语言程序设计(第3版)》题目集 习题7-4 求矩阵各行元素之和
- 浙大版《C语言程序设计(第3版)》题目集 习题7-6 统计大写辅音字母
- 浙大版《C语言程序设计(第3版)》题目集 习题7-7 字符串替换
- 浙大版《C语言程序设计(第3版)》题目集 习题8-10 输出学生成绩
- 浙大版《C语言程序设计(第3版)》题目集 习题9-1 时间换算
- 浙大版《C语言程序设计(第3版)》题目集 习题9-3 平面向量加法
- 浙大版《C语言程序设计(第3版)》题目集 习题9-4 查找书籍
- 浙大版《C语言程序设计(第3版)》题目集 习题9-5 通讯录排序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-5 找鞍点
- 浙大版《C语言程序设计(第3版)》题目集 练习5-1 求m到n之和