在将OpenNLP POS标签用于多个文本时加快速度

时间:2010-12-06 16:14:41

标签: java performance serialization nlp opennlp

我目前正在开发一个关键短语提取工具,该工具应该为网站上的文本或文档提供标记建议。当我遵循本文提出的方法时: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秒钟等待模型加载并在之后的200ms内使用它。)

我的第一个想法是序列化 POSTaggerME TokenizerME resp。)并在每次需要时使用Java的内置机制对其进行反序列化。不幸的是,这不起作用 - 它引发了一个例外。 (我确实从WEKA工具包中对分类器进行了序列化,最终将我的候选人分类,以便不必每次都建立(或训练)分类器。因此,我认为这也适用于POSTaggeME。不幸的是,这是不是这样的。)

在Tokenizer的情况下,我可以参考一个简单的 WhitespaceTokenizer ,这是一个较差的解决方案,但并没有那么糟糕:

tokenizer = WhitespaceTokenizer.INSTANCE;

但我没有看到这个选项可靠的POSTagger。

1 个答案:

答案 0 :(得分:1)

只需将您的标记化/ 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);
}