Как я могу разделить текст или абзац на предложения, используя парсер Стэнфорда?
Есть ли какой-либо метод, который может извлекать предложения, такие как getSentencesFromString()
, как это предусмотрено для Ruby?
Как я могу разделить текст или абзац на предложения, используя парсер Стэнфорда?
Есть ли какой-либо метод, который может извлекать предложения, такие как getSentencesFromString()
, как это предусмотрено для Ruby?
Вы можете проверить класс 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);
}
Я знаю, что уже есть принятый ответ... но обычно вы просто захватываете SentenceAnnotations из аннотированного документа.
// 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" из инициализации конвейера, это сэкономит вам время загрузки и обработки. Рок-н-ролл. ~ К
Есть пара вопросов с принятым ответом. Во-первых, токенизатор преобразует некоторые символы, такие как символ "в два символа". Во-вторых, присоединение к токенам текста обратно вместе с пробелом не возвращает тот же результат, что и раньше. Поэтому текст примера из принятого ответа преобразует введите текст нетривиальными способами.
Однако класс 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.
Использование пакета .net С#: Это разнесет предложения, вернет круглые скобки и сохранит оригинальные пробелы и знаки препинания:
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 и разделить "по всем аспектам". как второе предложение.
Вы можете довольно легко использовать теггер Stanford для этого.
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
}
С помощью простого AIP, предоставленного Stanford CoreNLP версии 3.6.0 или 3.7.0 (http://stanfordnlp.github.io/CoreNLP/#about)
Вот пример с 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>
Вы можете использовать препроцессор . Это очень легко. Просто подайте это имя файла.
for (List<HasWord> sentence : new DocumentPreprocessor(pathto/filename.txt)) {
//sentence is a list of words in a sentence
}
Отклонение в ответе @Kevin, которое решает вопрос, выглядит следующим образом:
for(CoreMap sentence: sentences) {
String sentenceText = sentence.get(TextAnnotation.class)
}
который получает вам информацию о предложениях, не беспокоясь о других аннотаторах.
Еще один элемент, который не рассматривается, кроме нескольких приведенных ниже ответов, заключается в том, как установить разделители предложений? Наиболее распространенный способ, по умолчанию, состоит в том, чтобы зависеть от обычных знаков препинания, которые указывают конец предложения. Существуют и другие форматы документов, с которыми можно столкнуться, чтобы нарисовать собранные корпуса, одна из которых является каждой строкой - это собственное предложение.
Чтобы установить разделители для DocumentPreprocessor в соответствии с принятыми ответами, вы должны использовать setSentenceDelimiter(String)
. Чтобы использовать подход к конвейеру, предложенный как в ответе @Kevin, можно было бы работать со свойствами ssplit. Например, чтобы использовать схему конца строки, предложенную в предыдущем абзаце, можно было бы установить свойство ssplit.eolonly
в true
использовать регулярное выражение для разделения текста на предложения, в использовании Regex, но в java я не знаю.
код
string [] предложения = Regex.Split(текст, @ "(? <= ['" "a-za-z] [\)] [\. \! \?])\s + (? = [ AZ])" );
90% работает
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+");
}
}