2015-05-12 2 views
9
ersetzt

Ich versuche, die Möglichkeit zu finden, Sätze durch "Auflösen" (Ersetzen Wörter) mit ihren Koreferenzen mit Stanford Corenlp Coreference-Modul neu zu schreiben.Wie man ein Wort durch seine repräsentativste Erwähnung mit Stanford CoreNLP-Modul

Die Idee ist, einen Satz wie folgt neu schreiben:

John zu Judys Haus fuhr. Er machte ihr Abendessen.

in

John fuhr Haus zu Judys. John machte Judy zum Abendessen.

Hier ist der Code, den ich mit dem herum täuscht habe:

jetzt
private void doTest(String text){ 
    Annotation doc = new Annotation(text); 
    pipeline.annotate(doc); 


    Map<Integer, CorefChain> corefs = doc.get(CorefChainAnnotation.class); 
    List<CoreMap> sentences = doc.get(CoreAnnotations.SentencesAnnotation.class); 


    List<String> resolved = new ArrayList<String>(); 

    for (CoreMap sentence : sentences) { 

     List<CoreLabel> tokens = sentence.get(CoreAnnotations.TokensAnnotation.class); 

     for (CoreLabel token : tokens) { 

      Integer corefClustId= token.get(CorefCoreAnnotations.CorefClusterIdAnnotation.class); 
      System.out.println(token.word() + " --> corefClusterID = " + corefClustId); 


      CorefChain chain = corefs.get(corefClustId); 
      System.out.println("matched chain = " + chain); 


      if(chain==null){ 
       resolved.add(token.word()); 
      }else{ 

       int sentINdx = chain.getRepresentativeMention().sentNum -1; 
       CoreMap corefSentence = sentences.get(sentINdx); 
       List<CoreLabel> corefSentenceTokens = corefSentence.get(TokensAnnotation.class); 

       String newwords = ""; 
       CorefMention reprMent = chain.getRepresentativeMention(); 
       System.out.println(reprMent); 
       for(int i = reprMent.startIndex; i<reprMent.endIndex; i++){ 
        CoreLabel matchedLabel = corefSentenceTokens.get(i-1); //resolved.add(tokens.get(i).word()); 
        resolved.add(matchedLabel.word()); 

        newwords+=matchedLabel.word()+" "; 

       } 




       System.out.println("converting " + token.word() + " to " + newwords); 
      } 


      System.out.println(); 
      System.out.println(); 
      System.out.println("-----------------------------------------------------------------"); 

     } 

    } 


    String resolvedStr =""; 
    System.out.println(); 
    for (String str : resolved) { 
     resolvedStr+=str+" "; 
    } 
    System.out.println(resolvedStr); 


} 

Der beste Ausgang ich in der Lage war, ist

John fuhr nach Judy 's' s Judy zu erreichen 's Haus. John machte Judy ihr Abendessen.

, die nicht sehr brillant ...

Ich bin mir ziemlich sicher, dass es eine viel einfachere Art und Weise zu tun, was ich zu erreichen versuchen.

Idealerweise möchte ich den Satz als eine Liste von CoreLabels reorganisieren, so dass ich die anderen Daten behalten konnte, die sie an sie angehängt haben.

Jede Hilfe wird geschätzt.

Antwort

7

Die Herausforderung besteht darin, sicherzustellen, dass das Token nicht Teil seiner repräsentativen Erwähnung ist. Zum Beispiel hat das Token "Judy" "Judy's" als seine repräsentative Erwähnung, also, wenn Sie es in der Phrase "Judy's" ersetzen, werden Sie mit dem doppelten "s" enden.

Sie können überprüfen, ob das Token Teil seiner repräsentativen Erwähnung ist, indem Sie deren Indizes vergleichen. Sie sollten das Token nur ersetzen, wenn sein Index entweder kleiner ist als der startIndex der repräsentativen Erwähnung, oder größer als der endIndex der repräsentativen Erwähnung. Ansonsten behältst du einfach das Token.

Der relevante Teil des Codes sieht nun wie folgt aus:

  if (token.index() < reprMent.startIndex || token.index() > reprMent.endIndex) { 

       for (int i = reprMent.startIndex; i < reprMent.endIndex; i++) { 
        CoreLabel matchedLabel = corefSentenceTokens.get(i - 1); 
        resolved.add(matchedLabel.word()); 

        newwords += matchedLabel.word() + " "; 

       } 
      } 

      else { 
       resolved.add(token.word()); 

      } 

Zusätzlich und um den Prozess zu beschleunigen, können Sie auch Ihre erste if-Bedingung ersetzen durch:

if (chain==null || chain.getMentionsInTextualOrder().size() == 1) 

Wenn die Länge der Co-Referenzkette nur 1 beträgt, ist es nicht sinnvoll, nach einer repräsentativen Erwähnung zu suchen.

+0

Vielen Dank für Ihre Antwort! Es hilft mir sehr. Gibt es im zweiten Satz einen generischen Weg, um herauszufinden, dass "sie" durch "Judy" und nicht "Judy" ersetzt werden sollte? Nach der ganzen Zieleinheit ist Judy. So gibt es einen Weg, entweder mit POS-Tags oder Parse-Tree, um die "s" loszuwerden. Ich habe noch nicht viele andere Sätze getestet, aber ich bin sicher, dass ich andere Beispiele finden werde. Danke noch einmal. – azpublic

+0

Ich denke du könntest das headIndex Attribut des Repräsentanten erwähnen um den Kopf des NP zu finden. – yvespeirsman

1
private void doTest(String text){ 
    Properties props = new Properties(); 
    props.put("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref"); 
    StanfordCoreNLP pipeline = new StanfordCoreNLP(props); 
    Annotation doc = new Annotation(text); 
    pipeline.annotate(doc); 


    Map<Integer, CorefChain> corefs = doc.get(CorefChainAnnotation.class); 
    List<CoreMap> sentences = doc.get(CoreAnnotations.SentencesAnnotation.class); 


    List<String> resolved = new ArrayList<String>(); 

    for (CoreMap sentence : sentences) { 

     List<CoreLabel> tokens = sentence.get(CoreAnnotations.TokensAnnotation.class); 

     for (CoreLabel token : tokens) { 

      Integer corefClustId= token.get(CorefCoreAnnotations.CorefClusterIdAnnotation.class); 
      System.out.println(token.word() + " --> corefClusterID = " + corefClustId); 


      CorefChain chain = corefs.get(corefClustId); 
      System.out.println("matched chain = " + chain); 


      if(chain==null){ 
       resolved.add(token.word()); 
       System.out.println("Adding the same word "+token.word()); 
      }else{ 

       int sentINdx = chain.getRepresentativeMention().sentNum -1; 
       System.out.println("sentINdx :"+sentINdx); 
       CoreMap corefSentence = sentences.get(sentINdx); 
       List<CoreLabel> corefSentenceTokens = corefSentence.get(TokensAnnotation.class); 
       String newwords = ""; 
       CorefMention reprMent = chain.getRepresentativeMention(); 
       System.out.println("reprMent :"+reprMent); 
       System.out.println("Token index "+token.index()); 
       System.out.println("Start index "+reprMent.startIndex); 
       System.out.println("End Index "+reprMent.endIndex); 
       if (token.index() <= reprMent.startIndex || token.index() >= reprMent.endIndex) { 

         for (int i = reprMent.startIndex; i < reprMent.endIndex; i++) { 
          CoreLabel matchedLabel = corefSentenceTokens.get(i - 1); 
          resolved.add(matchedLabel.word().replace("'s", "")); 
          System.out.println("matchedLabel : "+matchedLabel.word()); 
          newwords += matchedLabel.word() + " "; 

         } 
        } 

        else { 
         resolved.add(token.word()); 
         System.out.println("token.word() : "+token.word()); 
        } 



       System.out.println("converting " + token.word() + " to " + newwords); 
      } 


      System.out.println(); 
      System.out.println(); 
      System.out.println("-----------------------------------------------------------------"); 

     } 

    } 


    String resolvedStr =""; 
    System.out.println(); 
    for (String str : resolved) { 
     resolvedStr+=str+" "; 
    } 
    System.out.println(resolvedStr); 


} 

Gab perfekte Antwort.

John fuhr zu Judys Haus. Er machte ihr Abendessen. -----> John fuhr zu Judys Haus. John machte Judy zum Abendessen. Tom ist ein kluger Junge. Er weiß viel.-----> Tom ist ein kluger Tom. Tom weiß viel.

+0

'Tom ist ein kluger Tom' ist keine perfekte Antwort. –

+1

Junge wird hier Tom genannt. Also nicht grammatikalisch korrekt, aber technisch ja :) –

Verwandte Themen