我正在寻找优化斯坦福CoreNLP情绪管道性能的方法。因此,想要获得句子的情感,但只想包含作为输入的特定关键词。
我尝试了两种方法:
方法1:StanfordCoreNLP管道用情绪注释整个文本
我已经定义了一个注释器管道:tokenize,ssplit,parse,sentiment。我在整篇文章中运行它,然后在每个句子中查找关键字,如果它们存在,则运行返回关键字值的方法。虽然处理需要几秒钟,但我并不满意。
这是代码:
List<String> keywords = ...;
String text = ...;
Map<Integer,Integer> sentenceSentiment = new HashMap<>();
Properties props = new Properties();
props.setProperty("annotators", "tokenize, ssplit, parse, sentiment");
props.setProperty("parse.maxlen", "20");
props.setProperty("tokenize.options", "untokenizable=noneDelete");
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
Annotation annotation = pipeline.process(text); // takes 2 seconds!!!!
List<CoreMap> sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
for (int i=0; i<sentences.size(); i++) {
CoreMap sentence = sentences.get(i);
if(sentenceContainsKeywords(sentence,keywords) {
int sentiment = RNNCoreAnnotations.getPredictedClass(sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class));
sentenceSentiment.put(sentence,sentiment);
}
}
方法2:StanfordCoreNLP管道用句子注释整个文本,分离在感兴趣的句子上运行的注释器
由于第一个解决方案的性能较弱,我已经定义了第二个解决方案。我已经使用注释器定义了一个管道:tokenize,ssplit。我在每个句子中查找了关键字,如果它们存在,我只为这个句子创建了一个注释并在其上运行下一个注释器:ParserAnnotator,BinarizerAnnotator和SentimentAnnotator。
由于ParserAnnotator,结果真的不令人满意。即使我用相同的属性初始化它。有时,方法1中的文档运行时间比整个管道花费的时间更多。
List<String> keywords = ...;
String text = ...;
Map<Integer,Integer> sentenceSentiment = new HashMap<>();
Properties props = new Properties();
props.setProperty("annotators", "tokenize, ssplit"); // parsing, sentiment removed
props.setProperty("parse.maxlen", "20");
props.setProperty("tokenize.options", "untokenizable=noneDelete");
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
// initiation of annotators to be run on sentences
ParserAnnotator parserAnnotator = new ParserAnnotator("pa", props);
BinarizerAnnotator binarizerAnnotator = new BinarizerAnnotator("ba", props);
SentimentAnnotator sentimentAnnotator = new SentimentAnnotator("sa", props);
Annotation annotation = pipeline.process(text); // takes <100 ms
List<CoreMap> sentences = annotation.get(CoreAnnotations.SentencesAnnotation.class);
for (int i=0; i<sentences.size(); i++) {
CoreMap sentence = sentences.get(i);
if(sentenceContainsKeywords(sentence,keywords) {
// code required to perform annotation on one sentence
List<CoreMap> listWithSentence = new ArrayList<CoreMap>();
listWithSentence.add(sentence);
Annotation sentenceAnnotation = new Annotation(listWithSentence);
parserAnnotator.annotate(sentenceAnnotation); // takes 50 ms up to 2 seconds!!!!
binarizerAnnotator.annotate(sentenceAnnotation);
sentimentAnnotator.annotate(sentenceAnnotation);
sentence = sentenceAnnotation.get(CoreAnnotations.SentencesAnnotation.class).get(0);
int sentiment = RNNCoreAnnotations.getPredictedClass(sentence.get(SentimentCoreAnnotations.SentimentAnnotatedTree.class));
sentenceSentiment.put(sentence,sentiment);
}
}
问题
我想知道为什么在CoreNLP中解析不是“懒惰”? (在我的例子中,这意味着:只有在调用句子的情绪时才会执行)。这是出于业绩原因吗?
为什么一个句子的解析器几乎和整个文章的解析器一样长(我的文章有7个句子)?是否可以以更快的方式配置它?
答案 0 :(得分:5)
如果您希望加快选区解析,唯一最好的改进是使用新的shift-reduce constituency parser。它比默认的PCFG解析器快几个数量级。
以后问题的答案: