web-dev-qa-db-ja.com

Stanfordパーサーを使用してテキストを文に分割するにはどうすればよいですか?

Stanford parser を使用してテキストまたは段落を文に分割するにはどうすればよいですか?

Ruby に提供されているgetSentencesFromString()など、文を抽出できるメソッドはありますか?

27
S Gaber

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);
}
30
Kenston Choi

私はすでに受け入れられた回答があることを知っています...しかし、通常は注釈付きのドキュメントから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 (途中まで)

また、文のみを探している場合は、「解析」や「dcoref」などの後続のステップをパイプラインの初期化から削除できます。これにより、負荷と処理時間を節約できます。ロックンロール。 〜K

24
Kevin

受け入れられた回答にはいくつかの問題があります。最初に、トークナイザーは文字「」などの一部の文字を「2つの文字」に変換します。次に、トークン化されたテキストを空白で結合すると、以前と同じ結果が返されません。したがって、受け入れられた回答からのサンプルテキストは、入力テキストを重要な方法で変換します。

ただし、トークナイザーが使用する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.
16
dantiston

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

入力:-この文の文字には、句読点や散文でよく見られる魅力があります。これは2番目の文ですか。その通り。

出力: 3文( '?'は文の終わりの区切り文字と見なされます)

注:「ハビシャム夫人のクラスは、すべての面で(見ることができる限り)非の打ちどころのないものでした」のような文の場合。トークナイザーは、夫人の終わりの期間がEOSではないことを正しく認識しますが、誤って!括弧内はEOSとして、「すべての面で」分割されます。 2番目の文として。

8
Yaniv.H

Stanford CoreNLPバージョン3.6.0または3.7.0で提供される Simple API を使用。

これは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>
3
cindyxiaoxiaoli

これには、スタンフォードタガーをかなり簡単に使用できます。

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
}
1
Delirante

ドキュメントプリプロセッサ を使用できます。とても簡単です。ファイル名を入力するだけです。

    for (List<HasWord> sentence : new DocumentPreprocessor(pathto/filename.txt)) {
         //sentence is a list of words in a sentence
    }
1
bernie2436

いくつかの反対投票の回答を除いて扱われていない別の要素は、文の区切り文字を設定する方法ですか?最も一般的な方法は、デフォルトで、文の終わりを示す一般的な句読点に依存することです。収集されたコーパスを描くことから直面する可能性のある他のドキュメント形式があり、その1つは各行が独自の文です。

受け入れられた回答のようにDocumentPreprocessorの区切り文字を設定するには、setSentenceDelimiter(String)を使用します。 @Kevinの回答で提案されているパイプラインアプローチを使用するには、ssplitプロパティを使用します。たとえば、前の段落で提案された行末スキームを使用するには、プロパティssplit.eolonlytrueに設定します。

0
demongolem

以下のコードで入力ファイルと出力ファイルのパスを追加します:

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
Rahul Shah

質問を解決する@Kevin回答のバリエーションは次のとおりです。

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

他のアノテーターに迷惑をかけることなく文章情報を取得します。

0
demongolem