Как я могу разбить текст на предложения, используя анализатор Stanford? - PullRequest
26 голосов
/ 29 февраля 2012

Как разделить текст или абзац на предложения, используя Stanford parser ?

Существует ли какой-либо метод, который может извлекать предложения, например getSentencesFromString(), поскольку он предоставляется для Ruby ?

Ответы [ 12 ]

30 голосов
/ 29 февраля 2012

Вы можете проверить класс DocumentPreprocessor.Ниже приведен короткий фрагмент.Я думаю, что могут быть другие способы сделать то, что вы хотите.

String paragraph = "My 1st sentence. “Does it work for questions?” My third sentence.";
Reader reader = new StringReader(paragraph);
DocumentPreprocessor dp = new DocumentPreprocessor(reader);
List<String> sentenceList = new ArrayList<String>();

for (List<HasWord> sentence : dp) {
   // SentenceUtils not Sentence
   String sentenceString = SentenceUtils.listToString(sentence);
   sentenceList.add(sentenceString);
}

for (String sentence : sentenceList) {
   System.out.println(sentence);
}
24 голосов
/ 12 июня 2013

Я знаю, что уже есть принятый ответ ... но обычно вы просто берете аннотации предложений из аннотированного документа.

// creates a StanfordCoreNLP object, with POS tagging, lemmatization, NER, parsing, and coreference resolution 
Properties props = new Properties();
props.put("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref");
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);

// read some text in the text variable
String text = ... // Add your text here!

// create an empty Annotation just with the given text
Annotation document = new Annotation(text);

// run all Annotators on this text
pipeline.annotate(document);

// these are all the sentences in this document
// a CoreMap is essentially a Map that uses class objects as keys and has values with custom types
List<CoreMap> sentences = document.get(SentencesAnnotation.class);

for(CoreMap sentence: sentences) {
  // traversing the words in the current sentence
  // a CoreLabel is a CoreMap with additional token-specific methods
  for (CoreLabel token: sentence.get(TokensAnnotation.class)) {
    // this is the text of the token
    String word = token.get(TextAnnotation.class);
    // this is the POS tag of the token
    String pos = token.get(PartOfSpeechAnnotation.class);
    // this is the NER label of the token
    String ne = token.get(NamedEntityTagAnnotation.class);       
  }

}

Источник - http://nlp.stanford.edu/software/corenlp.shtml (на полпути вниз)

И если вы ищете только предложения, вы можете удалить последующие шаги, такие как "parse" и "dcoref", из инициализации конвейера, это сэкономит вам некоторую нагрузку и время обработки.Рок-н-ролл.~ K

16 голосов
/ 19 июня 2015

Есть пара вопросов с принятым ответом. Во-первых, токенизатор преобразует некоторые символы, такие как символ «в два символа` `. Во-вторых, объединение токенизированного текста обратно с пробелами не возвращает тот же результат, что и раньше. Поэтому пример текста из принятого ответа преобразует входной текст нетривиальными способами.

Однако класс CoreLabel, который использует токенизатор, отслеживает исходные символы, с которыми они сопоставлены, поэтому тривиально восстановить правильную строку, если у вас есть оригинал.

Подход 1, представленный ниже, показывает подход с использованием принятых ответов, Подход 2 показывает мой подход, который преодолевает эти проблемы.

String paragraph = "My 1st sentence. “Does it work for questions?” My third sentence.";

List<String> sentenceList;

/* ** APPROACH 1 (BAD!) ** */
Reader reader = new StringReader(paragraph);
DocumentPreprocessor dp = new DocumentPreprocessor(reader);
sentenceList = new ArrayList<String>();
for (List<HasWord> sentence : dp) {
    sentenceList.add(Sentence.listToString(sentence));
}
System.out.println(StringUtils.join(sentenceList, " _ "));

/* ** APPROACH 2 ** */
//// Tokenize
List<CoreLabel> tokens = new ArrayList<CoreLabel>();
PTBTokenizer<CoreLabel> tokenizer = new PTBTokenizer<CoreLabel>(new StringReader(paragraph), new CoreLabelTokenFactory(), "");
while (tokenizer.hasNext()) {
    tokens.add(tokenizer.next());
}
//// Split sentences from tokens
List<List<CoreLabel>> sentences = new WordToSentenceProcessor<CoreLabel>().process(tokens);
//// Join back together
int end;
int start = 0;
sentenceList = new ArrayList<String>();
for (List<CoreLabel> sentence: sentences) {
    end = sentence.get(sentence.size()-1).endPosition();
    sentenceList.add(paragraph.substring(start, end).trim());
    start = end;
}
System.out.println(StringUtils.join(sentenceList, " _ "));

Это выводит:

My 1st sentence . _ `` Does it work for questions ? '' _ My third sentence .
My 1st sentence. _ “Does it work for questions?” _ My third sentence.
7 голосов
/ 19 октября 2013

Использование пакета .net C #: это разделит предложения, получит правильные скобки и сохранит оригинальные пробелы и знаки препинания:

public class NlpDemo
{
    public static readonly TokenizerFactory TokenizerFactory = PTBTokenizer.factory(new CoreLabelTokenFactory(),
                "normalizeParentheses=false,normalizeOtherBrackets=false,invertible=true");

    public void ParseFile(string fileName)
    {
        using (var stream = File.OpenRead(fileName))
        {
            SplitSentences(stream);
        }
    }

    public void SplitSentences(Stream stream)
    {            
        var preProcessor = new DocumentPreprocessor(new UTF8Reader(new InputStreamWrapper(stream)));
        preProcessor.setTokenizerFactory(TokenizerFactory);

        foreach (java.util.List sentence in preProcessor)
        {
            ProcessSentence(sentence);
        }            
    }

    // print the sentence with original spaces and punctuation.
    public void ProcessSentence(java.util.List sentence)
    {
        System.Console.WriteLine(edu.stanford.nlp.util.StringUtils.joinWithOriginalWhiteSpace(sentence));
    }
}

Ввод: - символы этого предложения обладают определеннымочарование, часто встречающееся в пунктуации и прозе.Это второе предложение?Это действительно.

Вывод: 3 предложения ('?' Считается разделителем конца предложения)

Примечание: для предложения типа "Миссис Хэвишемкласс был безупречен (насколько можно было видеть!) во всех аспектах. "Токенизатор правильно распознает, что период в конце миссис не является EOS, однако он неправильно пометит!в скобках как EOS и разделить «во всех аспектах».как второе предложение.

3 голосов
/ 11 октября 2016

С Simple API , предоставленным Stanford CoreNLP версии 3.6.0 или 3.7.0.

Вот пример с 3.6.0.Он работает точно так же с 3.7.0.

Фрагмент кода Java

import java.util.List;

import edu.stanford.nlp.simple.Document;
import edu.stanford.nlp.simple.Sentence;
public class TestSplitSentences {
    public static void main(String[] args) {
        Document doc = new Document("The text paragraph. Another sentence. Yet another sentence.");
        List<Sentence> sentences = doc.sentences();
        sentences.stream().forEach(System.out::println);
    }
}

Выход:

Текстовый абзац.

Другойпредложение.

Еще одно предложение.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>stanfordcorenlp</groupId>
    <artifactId>stanfordcorenlp</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/edu.stanford.nlp/stanford-corenlp -->
        <dependency>
            <groupId>edu.stanford.nlp</groupId>
            <artifactId>stanford-corenlp</artifactId>
            <version>3.6.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
        <dependency>
            <groupId>com.google.protobuf</groupId>
            <artifactId>protobuf-java</artifactId>
            <version>2.6.1</version>
        </dependency>
    </dependencies>
</project>
1 голос
/ 24 ноября 2015

Для этого вы можете довольно легко использовать Stanford tagger.

String text = new String("Your text....");  //Your own text.
List<List<HasWord>> tokenizedSentences = MaxentTagger.tokenizeText(new StringReader(text));

for(List<CoreLabel> act : tokenizedSentences)       //Travel trough sentences
{
    System.out.println(edu.stanford.nlp.ling.Sentence.listToString(act)); //This is your sentence
}
0 голосов
/ 25 августа 2018

Добавить путь для входного и выходного файла в следующем коде: -

import java.util.*;
import edu.stanford.nlp.pipeline.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class NLPExample
{
    public static void main(String[] args) throws IOException 
    {
        PrintWriter out;
        out = new PrintWriter("C:\\Users\\ACER\\Downloads\\stanford-corenlp-full-     
        2018-02-27\\output.txt");
        Properties props=new Properties();
        props.setProperty("annotators","tokenize, ssplit, pos,lemma");
        StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
        Annotation annotation;  
        String readString = null;
        PrintWriter pw = null;
        BufferedReader br = null;
        br = new BufferedReader (new 
        FileReader("C:\\Users\\ACER\\Downloads\\stanford- 
        corenlp-full-2018-02-27\\input.txt" )  ) ;
        pw = new PrintWriter ( new BufferedWriter ( new FileWriter ( 
        "C:\\Users\\ACER\\Downloads\\stanford-corenlp-full-2018-02-   
        27\\output.txt",false 
        ))) ;      
        String x = null;
        while  (( readString = br.readLine ())  != null)
        {
            pw.println ( readString ) ; String 
            xx=readString;x=xx;//System.out.println("OKKKKK"); 
            annotation = new Annotation(x);
            pipeline.annotate(annotation);    //System.out.println("LamoohAKA");
            pipeline.prettyPrint(annotation, out);
        }
        br.close (  ) ;
        pw.close (  ) ;
        System.out.println("Done...");
    }    
}
0 голосов
/ 31 октября 2016

Еще один элемент, который не рассматривается, за исключением нескольких ответов с отрицательным голосом, - как установить разделители предложений? Наиболее распространенный способ, по умолчанию, состоит в том, чтобы зависеть от общих знаков препинания, которые указывают конец предложения. Существуют и другие форматы документов, с которыми можно столкнуться, опираясь на собранные корпуса, один из которых - каждая строка - это собственное предложение.

Чтобы установить разделители для DocumentPreprocessor, как в принятых ответах, вы должны использовать setSentenceDelimiter(String). Чтобы использовать конвейерный подход, предложенный в ответе @Kevin, нужно работать со свойствами ssplit. Например, чтобы использовать схему конца строки, предложенную в предыдущем абзаце, можно задать для свойства ssplit.eolonly значение true

.
0 голосов
/ 10 марта 2016

Вариант ответа @Kevin, который решит вопрос, таков:

for(CoreMap sentence: sentences) {
      String sentenceText = sentence.get(TextAnnotation.class)
}

, который дает вам информацию о предложении, не связываясь с другими аннотаторами.

0 голосов
/ 16 июля 2015
public class k {

public static void main(String a[]){

    String str = "This program splits a string based on space";
    String[] words = str.split(" ");
    for(String s:words){
        System.out.println(s);
    }
    str = "This     program  splits a string based on space";
    words = str.split("\\s+");
}
}
...