0

我正在评估将 OpenNLP 用作文档分类器。我有一个经过清理的训练语料库,包含大约 4k 个文件,大约 150 个类别。这些文档有许多共享的、大部分不相关的词——但其中许多词在 n-gram 中变得相关,所以我使用以下参数:

        TrainingParameters params = new TrainingParameters();
        params.put(TrainingParameters.ITERATIONS_PARAM, 20000);
        params.put(TrainingParameters.CUTOFF_PARAM, 10);
        DoccatFactory dcFactory = new DoccatFactory(new FeatureGenerator[] { new NGramFeatureGenerator(3, 10) });
        params.put(AbstractTrainer.ALGORITHM_PARAM, NaiveBayesTrainer.NAIVE_BAYES_VALUE);

其中一些类别适用于几乎完全相同的文档(想想样板法律文档,文档实例之间可能只有名称和地址不同) - 并且与测试集中的文档基本相同。但是,无论我如何调整这些参数,我都无法摆脱“1 个结果模式”的结果。运行测试时,测试集中的每个文档都被标记为“A 类”。

通过从以前使用 BagOfWordsFeatureGenerator 到 NGramFeatureGenerator,以及从 maxent 到朴素贝叶斯,我确实设法在输出中产生了一个小的变化;在更改之前,测试集中的每个文档都被分配到“A 类”,但在更改之后,所有文档现在都被分配到“B 类”。但除此之外,我似乎根本无法移动表盘。

我试过摆弄迭代、截止、ngram 大小、使用 maxent 而不是贝叶斯等;但一切都无济于事。

我在互联网上找到的教程示例代码使用了更小的训练集和更少的迭代,并且能够执行至少一些基本的差异化。

通常在这种情况下——令人眼花缭乱地缺乏预期的行为——工程师忘记拨动一些简单的开关,或者对基本的理解有一些致命的缺乏。我非常有能力应对这两种失败。此外,我没有接受过数据科学培训,尽管我已经阅读了 O'Reilly 的几本关于该主题的书籍。所以问题可能是程序性的。训练集是否太小?迭代次数是否减少了一个数量级?不同的算法会更合适吗?令我感到非常惊讶的是,没有任何调整甚至将刻度盘从“1 结果”结果中稍微移开。

任何回应表示赞赏。

4

1 回答 1

0

好吧,这个问题的答案并非来自提出问题的方向。事实证明,OpenNLP 文档中有一个代码示例是错误的,再多的参数调整也无法解决它。我已经向项目提交了一个 jira,所以它应该得到解决;但对于那些在那之前来到这里的人来说,这里是破败:

文档(错误):

String inputText = ...
DocumentCategorizerME myCategorizer = new DocumentCategorizerME(m);
double[] outcomes = myCategorizer.categorize(inputText);
String category = myCategorizer.getBestCategory(outcomes);

应该是这样的:

String inputText = ... // sanitized document to be classified
DocumentCategorizerME myCategorizer = new DocumentCategorizerME(m);
double[] outcomes = myCategorizer.categorize(inputText.split(" "));
String category = myCategorizer.getBestCategory(outcomes);

DocumentCategorizerME.categorize() 需要一个数组;因为这显然是你第二次运行代码时的自记录错误,所以我假设必要的数组参数应该是字符串形式的文档数组;相反,它需要来自单个文档的一组标记。

于 2020-08-25T21:58:16.127 回答