我一直在尝试使用TMT工具箱(stanford nlp group)从经过训练的标记LDA模型和pLDA推断代码。 我已经浏览了以下链接中提供的示例: http://nlp.stanford.edu/software/tmt/tmt-0.3/ http://nlp.stanford.edu/software/tmt/tmt-0.4/
以下是我正在尝试标记LDA推理的代码
val modelPath = file("llda-cvb0-59ea15c7-31-61406081-75faccf7");
val model = LoadCVB0LabeledLDA(modelPath);`
val source = CSVFile("pubmed-oa-subset.csv") ~> IDColumn(1);
val text = {
source ~> // read from the source file
Column(4) ~> // select column containing text
TokenizeWith(model.tokenizer.get) //tokenize with model's tokenizer
}
val labels = {
source ~> // read from the source file
Column(2) ~> // take column two, the year
TokenizeWith(WhitespaceTokenizer())
}
val outputPath = file(modelPath, source.meta[java.io.File].getName.replaceAll(".csv",""));
val dataset = LabeledLDADataset(text,labels,model.termIndex,model.topicIndex);
val perDocTopicDistributions = InferCVB0LabeledLDADocumentTopicDistributions(model, dataset);
val perDocTermTopicDistributions =EstimateLabeledLDAPerWordTopicDistributions(model, dataset, perDocTopicDistributions);
TSVFile(outputPath+"-word-topic-distributions.tsv").write({
for ((terms,(dId,dists)) <- text.iterator zip perDocTermTopicDistributions.iterator) yield {
require(terms.id == dId);
(terms.id,
for ((term,dist) <- (terms.value zip dists)) yield {
term + " " + dist.activeIterator.map({
case (topic,prob) => model.topicIndex.get.get(topic) + ":" + prob
}).mkString(" ");
});
}
});
错误
found : scalanlp.collection.LazyIterable[(String, Array[Double])]
required: Iterable[(String, scalala.collection.sparse.SparseArray[Double])]
EstimateLabeledLDAPerWordTopicDistributions(model, dataset, perDocTopicDistributions);
我理解这是一种类型不匹配错误。但我不知道如何为scala解决这个问题。 基本上我不明白我应该如何提取 1.每个文档主题分发 2.输出推断命令后的每个doc标签分发。
请帮忙。 同样是pLDA。 我达到了推理命令,之后无能为力。
答案 0 :(得分:4)
Scala类型系统比Java更复杂,理解它会让你成为更好的程序员。问题出在这里:
val perDocTermTopicDistributions =EstimateLabeledLDAPerWordTopicDistributions(model, dataset, perDocTopicDistributions);
因为模型,数据集或perDocTopicDistributions类型为:
scalanlp.collection.LazyIterable[(String, Array[Double])]
而EstimateLabeledLDAPerWordTopicDistributions.apply需要
Iterable[(String, scalala.collection.sparse.SparseArray[Double])]
调查此类型错误的最佳方法是查看ScalaDoc(例如,tmt的那个是:http://nlp.stanford.edu/software/tmt/tmt-0.4/api/#package)如果您无法轻易找到问题的位置,则应该明确类型您的代码中的变量如下所示:
val perDocTopicDistributions:LazyIterable[(String, Array[Double])] = InferCVB0LabeledLDADocumentTopicDistributions(model, dataset)
如果我们一起看看edu.stanford.nlp.tmt.stage的javadoc:
def
EstimateLabeledLDAPerWordTopicDistributions (model: edu.stanford.nlp.tmt.model.llda.LabeledLDA[_, _, _], dataset: Iterable[LabeledLDADocumentParams], perDocTopicDistributions: Iterable[(String, SparseArray[Double])]): LazyIterable[(String, Array[SparseArray[Double]])]
def
InferCVB0LabeledLDADocumentTopicDistributions (model: CVB0LabeledLDA, dataset: Iterable[LabeledLDADocumentParams]): LazyIterable[(String, Array[Double])]
现在应该清楚,InferCVB0LabeledLDADocumentTopicDistributions的返回不能直接用于提供EstimateLabeledLDAPerWordTopicDistributions。
我从未使用过stanford nlp,但这是设计api的工作方式,因此您只需要在调用函数之前将scalanlp.collection.LazyIterable[(String, Array[Double])]
转换为Iterable[(String, scalala.collection.sparse.SparseArray[Double])]
。
如果你看看scaladoc如何进行这种转换,那就很简单了。在包阶段内,在package.scala中,我可以阅读import scalanlp.collection.LazyIterable;
所以我知道在哪里看,实际上在http://www.scalanlp.org/docs/core/data/#scalanlp.collection.LazyIterable内你有一个toIterable方法将LazyIterable转换为Iterable,你仍然必须将你的内部数组转换为SparseArray
再次,我查看tmt中的stage包的package.scala,我看到:import scalala.collection.sparse.SparseArray;
我寻找scalala文档:
http://www.scalanlp.org/docs/scalala/0.4.1-SNAPSHOT/#scalala.collection.sparse.SparseArray
事实证明构造函数对我来说似乎很复杂,所以听起来很像我必须查看工厂方法的伴随对象。事实证明,我正在寻找的方法就在那里,并且它被称为像Scala一样照常应用。
def
apply [T] (values: T*)(implicit arg0: ClassManifest[T], arg1: DefaultArrayValue[T]): SparseArray[T]
通过使用它,您可以编写具有以下签名的函数:
def f: Array[Double] => SparseArray[Double]
完成此操作后,您可以使用一行代码将InferCVB0LabeledLDADocumentTopicDistributions的结果转换为稀疏数组的非延迟迭代:
result.toIterable.map { case (name, values => (name, f(values)) }