【问题标题】:Tree node mapping to GrammaticalStructure dependency树节点映射到 GrammaticalStructure 依赖项
【发布时间】:2015-10-09 13:52:26
【问题描述】:

我正在使用斯坦福核心 NLP 框架 3.4.1 来构建维基百科句子的句法分析树。之后,我想从每个解析树中提取一定长度的所有树片段(即最多 5 个节点),但是在不为每个子创建新的 GrammaticalStructure 的情况下,我很难弄清楚如何做到这一点-树。

这是我用来构建解析树的代码,大部分代码来自 TreePrint.printTreeInternal() 的 conll2007 格式,我对其进行了修改以满足我的输出需求:

    DocumentPreprocessor dp = new DocumentPreprocessor(new StringReader(documentText));

    for (List<HasWord> sentence : dp) {
        StringBuilder plaintexSyntacticTree = new StringBuilder();
        String sentenceString = Sentence.listToString(sentence);

        PTBTokenizer tkzr = PTBTokenizer.newPTBTokenizer(new StringReader(sentenceString));
        List toks = tkzr.tokenize();
        // skip sentences smaller than 5 words
        if (toks.size() < 5)
            continue;
        log.info("\nTokens are: "+PTBTokenizer.labelList2Text(toks));
        LexicalizedParser lp = LexicalizedParser.loadModel(
        "edu/stanford/nlp/models/lexparser/englishPCFG.ser.gz",
        "-maxLength", "80");
        TreebankLanguagePack tlp = new PennTreebankLanguagePack();
        GrammaticalStructureFactory gsf = tlp.grammaticalStructureFactory();
        Tree parse = lp.apply(toks);
        GrammaticalStructure gs = gsf.newGrammaticalStructure(parse);
        Collection<TypedDependency> tdl = gs.allTypedDependencies();
        Tree it = parse.deepCopy(parse.treeFactory(), CoreLabel.factory());
        it.indexLeaves();

        List<CoreLabel> tagged = it.taggedLabeledYield();
        // getSortedDeps
        List<Dependency<Label, Label, Object>> sortedDeps = new ArrayList<Dependency<Label, Label, Object>>();
        for (TypedDependency dep : tdl) {
            NamedDependency nd = new NamedDependency(dep.gov().label(), dep.dep().label(), dep.reln().toString());
            sortedDeps.add(nd);
        }
        Collections.sort(sortedDeps, Dependencies.dependencyIndexComparator());

        for (int i = 0; i < sortedDeps.size(); i++) {
          Dependency<Label, Label, Object> d = sortedDeps.get(i);

          CoreMap dep = (CoreMap) d.dependent();
          CoreMap gov = (CoreMap) d.governor();

          Integer depi = dep.get(CoreAnnotations.IndexAnnotation.class);
          Integer govi = gov.get(CoreAnnotations.IndexAnnotation.class);

          CoreLabel w = tagged.get(depi-1);

          // Used for both course and fine POS tag fields
          String tag = PTBTokenizer.ptbToken2Text(w.tag());

          String word = PTBTokenizer.ptbToken2Text(w.word());

          if (plaintexSyntacticTree.length() > 0)
              plaintexSyntacticTree.append(' ');
          plaintexSyntacticTree.append(word+'/'+tag+'/'+govi);
        }
        log.info("\nTree is: "+plaintexSyntacticTree);
    }

在输出中我需要得到这种格式的东西:word/Part-Of-Speech-tag/parentID,它与Google Syntactic N-Grams的输出兼容

我无法弄清楚,我如何才能从原始句法分析树(据我了解作为依赖项列表存储在 GrammaticalStructure 中)仅针对来自原始树。

我也看到了一些关于 HeadFinder 的提及,但据我所知,这仅对构建 GrammaticalStructure 有用,而我正在尝试使用现有的。 我还看到了一个关于converting GrammaticalStructure to Tree 的类似问题,但这仍然是一个悬而未决的问题,它没有解决子树或创建自定义输出的问题。我没有从 GrammaticalStructure 创建树,而是在想我可以只使用树中的节点引用来获取我需要的信息,但我基本上错过了 getNodeByIndex() 的等价物,它可以从 GrammaticalStructure 中按节点获取索引。

更新:我已经设法按照答案中的建议使用 SemanticGraph 获取所有必需的信息。这是一个基本的 sn-p 代码:

    String documentText = value.toString();
    Properties props = new Properties();
    props.put("annotators", "tokenize,ssplit,pos,depparse");
    StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
    Annotation annotation = new Annotation(documentText);
    pipeline.annotate(annotation);
    List<CoreMap> sentences =  annotation.get(CoreAnnotations.SentencesAnnotation.class);

    if (sentences != null && sentences.size() > 0) {
        CoreMap sentence = sentences.get(0);
        SemanticGraph sg = sentence.get(SemanticGraphCoreAnnotations.CollapsedDependenciesAnnotation.class);
        log.info("SemanticGraph: "+sg.toDotFormat());
       for (SemanticGraphEdge edge : sg.edgeIterable()) {
           int headIndex = edge.getGovernor().index();
           int depIndex = edge.getDependent().index();
           log.info("["+headIndex+"]"+edge.getSource().word()+"/"+depIndex+"/"+edge.getSource().get(CoreAnnotations.PartOfSpeechAnnotation.class));
       }
    }

【问题讨论】:

    标签: java tree nlp stanford-nlp


    【解决方案1】:

    Google 语法 n-gram 使用依赖树而不是选区树。因此,确实,获得该表示的唯一方法是将树转换为依赖树。您从选区解析中获得的父 ID 将用于中间节点,而不是句子中的另一个词。

    我的建议是运行依赖解析器注释器 (annotators = tokenize,ssplit,pos,depparse),并从生成的 SemanticGraph 中提取 5 个相邻节点的所有集群。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-16
      • 1970-01-01
      • 2016-10-04
      • 2016-02-12
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多