当前位置: 首页 > 知识库问答 >
问题:

使用Stanford CoreNLP进行惰性解析,只获取特定句子的情感

景帅
2023-03-14

我正在寻找优化斯坦福大学CoreNLP情绪管道性能的方法。因此,a希望获得句子的情感,但只希望获得那些包含特定关键字作为输入的句子。

我尝试了两种方法:

方法1:StanfordCoreNLP管道用情感注释整个文本

我定义了一个注释器管道:标记化、ssplit、解析和情感。我在整篇文章中运行了它,然后在每个句子中查找关键字,如果它们存在,运行一个返回关键字值的方法。虽然处理过程需要几秒钟,但我并不满意。

以下是代码:

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管道用句子注释整个文本,单独的注释器在感兴趣的句子上运行

由于第一个解决方案的性能较差,我定义了第二个解决方案。我定义了一个带有注释器的管道:标记化、ssplit。我在每个句子中寻找关键词,如果它们存在,我只为这个句子创建了一个注释,并在其上运行下一个注释器:ParserAnotator、BinarizerAnotator和感伤注释器。

由于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个句子)?是否可以以更快的方式配置它?

  • 共有1个答案

    劳华灿
    2023-03-14

    如果您希望加快选区解析的速度,那么最好的改进就是使用新的shift-reduce选区解析器。它比默认的PCFG解析器快几个数量级。

    以下是您后面问题的答案:

    1. 为什么CoreNLP解析不懒惰?这当然是可能的,但我们还没有实现。我们可能还没有看到很多内部用例需要这样做。如果您有兴趣制作一个“懒惰的注释器包装”,我们将很乐意接受您的贡献
    2. 为什么一个句子的语法分析器的工作时间几乎和整篇文章的语法分析器一样长?默认的斯坦福PCFG解析器是相对于句子长度的立方时间复杂度。这就是为什么出于性能原因,我们通常建议限制最大句子长度。另一方面,shift-reduce解析器相对于句子长度在线性时间内运行
     类似资料:
    • 如果我有一个实体和一些惰性集合(、、,...),并且希望编写一个JpaRepository-method,该方法为我提供所有的人,这些人都渴望获取,这可能吗? 我知道人们可以在单个物体上做到这一点,但这在某种程度上可以在人的集合上做到吗?

    • OpenNLP是一个关于自然语言处理的Apache项目。NLP程序的目的之一是解析一个句子,给出其语法结构的树。例如,句子“天空是蓝色的”可能被解析为 其中是句子,是名词短语,是动词短语。等效地,上面的树可以写成一个带括号的字符串,如下所示: 我试图使用OpenNLP从句子中获取带括号的字符串,但我无法让示例代码正常工作。 特别是,我正在遵循本教程的最后一部分,我的代码在初始化时卡住了。 我已经从

    • 我的理解是,默认情况下,Hibernate将所有关系类型的FetchType设置为lazy。 在我的例子中,我有一个双向的OneToMany-ManyToOne关系,如下所示: 另一个问题是我如何得到一个有特定名字的孩子?是否可以通过存储库进行操作?还是需要getChildren(parentId)并迭代直到找到以特定方式命名的那个? 编辑:在一些建议之后,我继续这样实现了我的ChildRepos

    • 问题内容: 有没有办法使用jQuery获得块内容的第5行(第一个字母的偏移量)? 我的意思是可视线,浏览器计算的线,而不是源代码中的线。 问题答案: jQuery.fn.line: 用法: 示例: http : //jsbin.com/akave 这个怎么运作: 它遍历整个元素(实际上是元素的克隆),并 在每个单词中插入一个元素。跨度的最高偏移量已缓存- 当此偏移量更改时,我们可以假定我们在新行上

    • 我有一个SVG文档,其中包含类似于以下内容的节点: 我想做的只是选择

    • 假设我有+10000个句子,我想像这个例子一样分析。有可能并行处理这些和多线程吗?