如何使用Stanford CoreNLP Coreferences模块以最具代表性的提及替换单词

azp*_*lic 11 java nlp stanford-nlp

我试图找出通过使用Stanford Corenlp的Coreference模块"解析"(用其替换单词)来重写句子的方法.

想法是重写一个如下句子:

约翰开车去了朱迪的家.他做了晚饭.

约翰开车去了朱迪的家.约翰做了朱迪的晚餐.

这是我一直在愚弄的代码:

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


}
Run Code Online (Sandbox Code Playgroud)

我现在能够实现的最佳输出是

约翰开车去朱迪的朱迪家.约翰让朱迪吃了她的晚餐.

这不是很精彩......

我很确定有更简单的方法来做我想要实现的目标.

理想情况下,我想将句子重新组织为CoreLabels列表,以便我可以保留他们附加到其上的其他数据.

任何帮助赞赏.

yve*_*man 9

挑战是您需要确保令牌不是其代表性提及的一部分.例如,令牌"Judy"有"Judy's"作为其代表性提及,所以如果你用短语"Judy's"取代它,你最终会得到双重"s".

您可以通过比较它们的指数来检查令牌是否是其代表性提及的一部分.如果令牌的索引小于startIndex代表性提及的索引,或者大于代表性提及的索引,则应该只替换该令牌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());

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

                }
            }

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

            }
Run Code Online (Sandbox Code Playgroud)

此外,为了加快这一过程,您还可以通过以下方式替换您的第一个if条件:

if (chain==null || chain.getMentionsInTextualOrder().size() == 1)
Run Code Online (Sandbox Code Playgroud)

毕竟,如果共同参考链的长度仅为1,则没有必要寻找代表性的提及.