2010-12-06 18 views
2

我目前正在研究一种关键词提取工具,它应该为网站上的文本或文档提供标签建议。正如我遵循本文提出的方法:A New Approach to Keyphrase Extraction Using Neural Networks我使用OpenNLP工具包的第一步,即候选人选择。加速使用OpenNLP的多种文本时的邮戳

一般来说,关键词提取工作得很好。我的问题是,我从他们相应的文件,我想用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之后。)

我的第一个想法是序列化POSTaggerMETokenizerME RESP)和反序列化它每次都需要使用Java的内置机制。不幸的是,这不起作用 - 它引发了一个例外。 (我将WEKA工具包中的分类器序列化,该分类器最后将我的候选人进行分类,以便不必每次都构建(或训练)分类器,因此我认为这也适用于POSTaggeME。 。不是这样的)

在标记生成器的情况下,我可以指一个简单的WhitespaceTokenizer这是一个劣解,但不是坏的:

tokenizer = WhitespaceTokenizer.INSTANCE; 

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

+0

当你说你想序列化对象,你的意思是序列化到磁盘上?似乎没有任何理由认为这会比再次加载模型(从磁盘)更快。我认为答案在于将模型保存在内存中,但我对您所部署的环境了解不足。 – Stompchicken 2010-12-06 17:13:51

+0

是的我想将其序列化到磁盘。我的动机是我认为这与WEKA分类器的序列化相似。但是我现在意识到它不是:在分类器的情况下,实际使用的内存大小相当小(而创建它的过程非常耗时) - 对于POSTagger,不能减小模型。所以也许我可以利用Singleton将所有内容加载到内存中一次。但在这种情况下,如果许多处理程序试图同时访问它,我可能会遇到问题。 – philonous 2010-12-06 17:31:21

回答

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); 
}