Análisis perezoso con Stanford CoreNLP para obtener sentimientos solo de oraciones específicas

Estoy buscando formas de optimizar el rendimiento de mi canal de sentimientos de Stanford CoreNLP. Como resultado, desea obtener el sentimiento de las oraciones, pero solo aquellas que contienen palabras clave específicas dadas como entrada.

He intentado dos enfoques:

Enfoque 1: canalización StanfordCoreNLP que anota todo el texto con sentimiento

He definido una tubería de anotadores: tokenize, ssplit, parse, sentiment. Lo ejecuté en todo el artículo, luego busqué palabras clave en cada oración y, si estaban presentes, ejecuté un método que devuelve el valor de la palabra clave. Aunque no estaba satisfecho, el procesamiento lleva un par de segundos.

Este es el código:

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

Enfoque 2: canalización StanfordCoreNLP que anota todo el texto con oraciones, anotadores separados que se ejecutan en oraciones de interés

Debido al bajo rendimiento de la primera solución, he definido la segunda solución. He definido una tubería con anotadores: tokenize, ssplit. Busqué palabras clave en cada oración y, si estaban presentes, he creado una anotación solo para esta oración y ejecuté los siguientes anotadores: ParserAnnotator, BinarizerAnnotator y SentimentAnnotator.

Los resultados fueron realmente insatisfactorios debido a ParserAnnotator. Incluso si lo inicialicé con las mismas propiedades. A veces, se tardó incluso más tiempo que la tubería completa ejecutada en un documento en el Método 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);
    }
}

Preguntas

Me pregunto por qué analizar en CoreNLP no es "vago". (En mi ejemplo, eso significaría: realizado solo cuando se invoca el sentimiento en una oración). ¿Es por razones de rendimiento?

¿Cómo es que un analizador para una oración puede funcionar casi tanto como un analizador para todo el artículo (mi artículo tenía 7 oraciones)? ¿Es posible configurarlo de manera que funcione más rápido?

Respuestas a la pregunta(1)

Su respuesta a la pregunta