使用经过训练的 MALLET 主题模型从相关主题中提取关键字
Extracting keywords from relevant topics using a trained MALLET Topic model
我正在尝试使用 MALLET 的 TopicInferencer
通过经过训练的模型从任意文本中推断关键字。到目前为止,我的总体做法如下。
- 使用大量已知训练数据训练
ParallelTopicModel
以创建主题集合。我目前正在使用一个包含 250,000 行的培训文件来创建 5,000 个主题。
- 根据不在训练模型中的任意文本创建
InstanceList
。
- 使用经过训练的模型的
topicInferencer.getSampledDistribution
生成针对模型的未知文本的主题分布。
- 对返回的分布进行排序并提取与未知输入文本匹配的前
n
个主题的 ID。
- 从每个匹配的主题中提取最热门的关键字。
我的代码如下:
正在生成 ParallelTopicModel
InstanceList instanceList = new InstanceList(makeSerialPipeList());
instanceList.addThruPipe(new SimpleFileLineIterator(trainingFile)); //training file with one entry per line (around 250,000 lines)
//should train a model with the end result being 5000 topics each with a collection of words
ParallelTopicModel parallelTopicModel = new ParallelTopicModel(
5000, //number of topics, I think with a large sample size we should want a large collection of topics
1.0D, //todo: alphaSum, really not sure what this does
0.01D //todo: beta, really not sure what this does
);
parallelTopicModel.setOptimizeInterval(20); //todo: read about this
parallelTopicModel.addInstances(instanceList);
parallelTopicModel.setNumIterations(2000);
parallelTopicModel.estimate();
我的第一组问题与创建 ParallelTopicModel
有关。
因为我使用的是相当大的培训文件,所以我想我需要大量的主题。我的逻辑是,主题数量越多,推断出的关键字越接近匹配任意输入文本。
我也不确定 alphaSum beta 值和迭代次数将如何影响生成的模型。
另一方面,我正在使用 ParallelTopicModel
创建推断的主题分布。
TopicInferencer topicInferencer = parallelTopicModel.getInferencer();
String document = //arbitrary text not in trained model
//following the format I found in SimpleFileLineIterator to create an Instance out of a document
Instance instance = new Instance(document, null, new URI("array:" + 1), null);
InstanceList instanceList = new InstanceList(serialPipes); //same SerialPipes used to create the InstanceList used for the ParallelTopicModel
instanceList.addThruPipe(instance);
//this should return the array of topicIDs and the match value
//[topicId] = 0.5 //match value
double[] topicDistribution =
topicInferencer.getSampledDistribution(instanceList.get(0), //extract text
2000, //same iteration count used in the model
1, //todo: thinning, not sure what this does
5 //todo: burnIn, not sure what this does
);
//returns a sorted list of the top 5 topic IDs
//this should be the index of the largest values in the returned topicDistribution
List<Integer> topIndexes = topIndexes(topicDistribution, 5); //top 5 topic indexes
//list topics and sorted keywords
ArrayList<TreeSet<IDSorter>> sortedWords = parallelTopicModel.getSortedWords();
//loop over the top indexes
topIndexes.forEach(index -> {
IDSorter idSorter = sortedWords.get(index).first(); //should hopefully be the first keyword in each topic
//not sure what alphabet I should use here or if it really matters?
//I passed in the alphabet from the original instance list as well as the one contained on our model
Object result = parallelTopicModel.getAlphabet().lookupObject(idSorter.getID());
double weight = idSorter.getWeight();
String formattedResult = String.format("%s:%.0f", result, weight);
//I should now have a relevant keyword and a weight in my result
});
我这里有一组类似的问题,首先我不完全确定这种总体方法是否正确。
我也不确定我应该使用什么 Alphabet
,我的 InstanceList
中用于生成 ParallelTopicModel
的那个还是直接从 ParallelTopicModel
.
我知道这是一个相当复杂的问题,但任何见解都将不胜感激!
alphaSum
和 beta
:这些控制您希望估计的文档主题和主题词分布的集中程度。较小的值鼓励更集中的分布和更少的移动。较大的值鼓励更平坦、更均匀的分布,以及更多的移动。用物理学术语来说,想想 "high energy" 与 "low energy".
1.0 for alphaSum
处于低端,5.0 可能更安全。 beta
的 0.01 几乎总是可以的。这并不重要,因为您正在使用超参数优化 (setOptimizeInterval
)。这将根据估计的主题拟合 alpha
值。您可能还想将老化周期设置为小于默认值的值,例如 25。这是开始优化之前扫描数据的次数。
主题数量:5000 个对于 250k 的文本段来说已经很多了。我将从 500 个开始。通过超参数优化,您将获得一些大型的通用主题和许多小型的特定主题。我的猜测是,如果有 5000 个主题,其中大部分(至少一半)基本上是空的。这在某种程度上是好的,因为这意味着模型正在自适应地选择其主题限制。但这也意味着您的主题只有很少的数据支持,看起来像是随机词。它还会在推理时引起问题:如果模型发现一个文档不适合任何 "real" 主题,它可以将其放入一个空主题中。
推断:2000 次迭代对于推断新文档的主题分布来说太多了。 10个应该够了。给定一个固定的、已经学过的模型,对一个文档的主题进行抽样 比从头开始学习模型要容易得多 。得到的分布是几个采样状态的平均值。它将忽略开始时的 burnin
个状态,然后在保存的样本之间跳过 thinning
个状态。
字母表应该无关紧要。您可以假设相同的 id 会产生相同的字符串。如果训练字母表和测试字母表不兼容,推理将无法进行。
我正在尝试使用 MALLET 的 TopicInferencer
通过经过训练的模型从任意文本中推断关键字。到目前为止,我的总体做法如下。
- 使用大量已知训练数据训练
ParallelTopicModel
以创建主题集合。我目前正在使用一个包含 250,000 行的培训文件来创建 5,000 个主题。 - 根据不在训练模型中的任意文本创建
InstanceList
。 - 使用经过训练的模型的
topicInferencer.getSampledDistribution
生成针对模型的未知文本的主题分布。 - 对返回的分布进行排序并提取与未知输入文本匹配的前
n
个主题的 ID。 - 从每个匹配的主题中提取最热门的关键字。
我的代码如下:
正在生成 ParallelTopicModel
InstanceList instanceList = new InstanceList(makeSerialPipeList());
instanceList.addThruPipe(new SimpleFileLineIterator(trainingFile)); //training file with one entry per line (around 250,000 lines)
//should train a model with the end result being 5000 topics each with a collection of words
ParallelTopicModel parallelTopicModel = new ParallelTopicModel(
5000, //number of topics, I think with a large sample size we should want a large collection of topics
1.0D, //todo: alphaSum, really not sure what this does
0.01D //todo: beta, really not sure what this does
);
parallelTopicModel.setOptimizeInterval(20); //todo: read about this
parallelTopicModel.addInstances(instanceList);
parallelTopicModel.setNumIterations(2000);
parallelTopicModel.estimate();
我的第一组问题与创建 ParallelTopicModel
有关。
因为我使用的是相当大的培训文件,所以我想我需要大量的主题。我的逻辑是,主题数量越多,推断出的关键字越接近匹配任意输入文本。
我也不确定 alphaSum beta 值和迭代次数将如何影响生成的模型。
另一方面,我正在使用 ParallelTopicModel
创建推断的主题分布。
TopicInferencer topicInferencer = parallelTopicModel.getInferencer();
String document = //arbitrary text not in trained model
//following the format I found in SimpleFileLineIterator to create an Instance out of a document
Instance instance = new Instance(document, null, new URI("array:" + 1), null);
InstanceList instanceList = new InstanceList(serialPipes); //same SerialPipes used to create the InstanceList used for the ParallelTopicModel
instanceList.addThruPipe(instance);
//this should return the array of topicIDs and the match value
//[topicId] = 0.5 //match value
double[] topicDistribution =
topicInferencer.getSampledDistribution(instanceList.get(0), //extract text
2000, //same iteration count used in the model
1, //todo: thinning, not sure what this does
5 //todo: burnIn, not sure what this does
);
//returns a sorted list of the top 5 topic IDs
//this should be the index of the largest values in the returned topicDistribution
List<Integer> topIndexes = topIndexes(topicDistribution, 5); //top 5 topic indexes
//list topics and sorted keywords
ArrayList<TreeSet<IDSorter>> sortedWords = parallelTopicModel.getSortedWords();
//loop over the top indexes
topIndexes.forEach(index -> {
IDSorter idSorter = sortedWords.get(index).first(); //should hopefully be the first keyword in each topic
//not sure what alphabet I should use here or if it really matters?
//I passed in the alphabet from the original instance list as well as the one contained on our model
Object result = parallelTopicModel.getAlphabet().lookupObject(idSorter.getID());
double weight = idSorter.getWeight();
String formattedResult = String.format("%s:%.0f", result, weight);
//I should now have a relevant keyword and a weight in my result
});
我这里有一组类似的问题,首先我不完全确定这种总体方法是否正确。
我也不确定我应该使用什么 Alphabet
,我的 InstanceList
中用于生成 ParallelTopicModel
的那个还是直接从 ParallelTopicModel
.
我知道这是一个相当复杂的问题,但任何见解都将不胜感激!
alphaSum
和 beta
:这些控制您希望估计的文档主题和主题词分布的集中程度。较小的值鼓励更集中的分布和更少的移动。较大的值鼓励更平坦、更均匀的分布,以及更多的移动。用物理学术语来说,想想 "high energy" 与 "low energy".
1.0 for alphaSum
处于低端,5.0 可能更安全。 beta
的 0.01 几乎总是可以的。这并不重要,因为您正在使用超参数优化 (setOptimizeInterval
)。这将根据估计的主题拟合 alpha
值。您可能还想将老化周期设置为小于默认值的值,例如 25。这是开始优化之前扫描数据的次数。
主题数量:5000 个对于 250k 的文本段来说已经很多了。我将从 500 个开始。通过超参数优化,您将获得一些大型的通用主题和许多小型的特定主题。我的猜测是,如果有 5000 个主题,其中大部分(至少一半)基本上是空的。这在某种程度上是好的,因为这意味着模型正在自适应地选择其主题限制。但这也意味着您的主题只有很少的数据支持,看起来像是随机词。它还会在推理时引起问题:如果模型发现一个文档不适合任何 "real" 主题,它可以将其放入一个空主题中。
推断:2000 次迭代对于推断新文档的主题分布来说太多了。 10个应该够了。给定一个固定的、已经学过的模型,对一个文档的主题进行抽样 比从头开始学习模型要容易得多 。得到的分布是几个采样状态的平均值。它将忽略开始时的 burnin
个状态,然后在保存的样本之间跳过 thinning
个状态。
字母表应该无关紧要。您可以假设相同的 id 会产生相同的字符串。如果训练字母表和测试字母表不兼容,推理将无法进行。