我目前正在使用关键字提取工具,该工具应该为网站上的文本或文档提供标签建议。当我遵循本文提出的方法时:A New Approach to Keyphrase Extraction Using Neural Networks第一步,我将使用OpenNLP工具箱的POSTagger,即候选人选择。

通常,关键词提取非常有效。我的问题是,每次我想使用POSTagger时,都必须从其对应的文件中进行模型的昂贵加载:

posTagger = new POSTaggerME(new POSModel(new FileInputStream(new File(modelDir + "/en-pos-maxent.bin"))));
tokenizer = new TokenizerME(new TokenizerModel(new FileInputStream(new File(modelDir + "/en-token.bin"))));
// ...
String[] tokens = tokenizer.tokenize(text);
String[] tags = posTagger.tag(tokens);


这是由于以下事实:此代码不在Web服务器本身的范围内,而是在具有生命周期的“处理程序”内部,该生命周期仅包括处理一个特定的请求。我的问题是:如何才能只加载一次文件? (我不想花10秒等待模型加载,然后只使用200毫秒。)

我的第一个想法是序列化POSTaggerME(TokenizerME分别),并在每次需要时使用Java的内置机制对它进行反序列化。不幸的是,这行不通–它引发了异常。 (我确实从WEKA工具包中对分类器进行了序列化,该工具包最后对我的候选人进行了分类,以便不必每次都构建(或训练)分类器。因此,我认为这也可能适用于POSTaggeME。不幸的是,这是并非如此。)

在Tokenizer的情况下,我可以引用一个简单的WhitespaceTokenizer,它是一个劣等的解决方案,但一点也不差劲:

tokenizer = WhitespaceTokenizer.INSTANCE;


但是我看不到可靠的POSTagger选项。

最佳答案

只需将标记化/ POS标记管道包装在singleton中。

如果基础的OpenNLP代码不是线程安全的,则将调用置于同步块中,例如:

// the singletons tokenization/POS-tagging pipeline
String[] tokens;
synchronized(tokenizer) {
   tokens = tokenizer.tokenize(text);
}
String[] tags;
synchronized(posTagger) {
   tags = posTagger.tag(tokens);
}

09-11 20:31