2015-05-12 11 views
9

Sto cercando di capire come riscrivere le frasi risolvendo (sostituendo le parole con) le loro coreferenze utilizzando il modulo Coreferenza di Stanford Corenlp.Come sostituire una parola con la sua menzione più rappresentativa utilizzando il modulo Stanford CoreNLP Coreferences

L'idea è quella di riscrivere una frase come la seguente:

John ha spinto a casa di Judy. La fece cenare.

in

John ha spinto a casa di Judy. John ha fatto cena a Judy.

Ecco il codice che ho scherzare con:

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


} 

L'uscita migliore sono stato in grado di ottenere per ora è

John ha spinto a Judy 's' s Judy La casa John ha fatto la cena a Judy.

che non è molto brillante ...

Sono abbastanza sicuro che c'è un modo molto più semplice per fare quello che sto cercando di realizzare.

Idealmente, mi piacerebbe riorganizzare la frase come un elenco di CoreLabels, in modo da poter conservare gli altri dati a cui sono collegati.

Qualsiasi aiuto apprezzato.

risposta

7

La sfida è che è necessario assicurarsi che il token non faccia parte della sua menzione rappresentativa. Ad esempio, il token "Judy" ha "Judy" come sua citazione rappresentativa, quindi se lo sostituisci nella frase "Judy's", finirai con il doppio "s".

È possibile verificare se il token fa parte della sua citazione rappresentativa confrontando i loro indici. Sostituire il token solo se il suo indice è più piccolo dello startIndex della menzione di rappresentante o superiore allo endIndex della menzione di rappresentante. Altrimenti tieni solo il token.

La parte rilevante del codice sarà ora simile a questa:

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

      } 

In aggiunta, e per accelerare il processo, è possibile anche sostituire il vostro primo se-condizione per:

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

Dopo tutto, se la lunghezza della catena di co-referenza è solo 1, non serve cercare una menzione rappresentativa.

+0

Grazie mille per la risposta! Mi aiuta molto. Nella seconda frase, c'è un modo generico per capire che "lei" dovrebbe essere sostituita da "Judy" e non "Judy's". Dopo tutto l'entità target è Judy. Quindi esiste un modo con tag pos o albero di analisi per sbarazzarsi delle "s". Non ho ancora provato molte altre frasi, ma sono sicuro che troverò altri esempi. Grazie ancora. – azpublic

+0

Immagino che potresti farti l'attributo headIndex della citazione rappresentante per trovare il capo del NP. – 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); 


} 

Ha risposto perfettamente.

John è andato a casa di Judy. La fece cenare. -----> John guidò fino alla casa di Judy. John ha fatto cena a Judy. Tom è un ragazzo intelligente. Lui sa un sacco di cose.-----> Tom è un Tom intelligente. Tom sa un sacco di cose.

+0

'Tom è un Tom intelligente 'non è una risposta perfetta. –

+1

Il ragazzo viene chiamato Tom qui. Quindi non è grammaticalmente corretto, ma tecnicamente sì :) –

Problemi correlati