解决如何在管道中概念上处理方括号与括号的问题



当我解析包含左右方括号的句子时,解析速度比包含左括号和右括号的句子慢得多,并且保留默认的 normalizeOtherBrackets 值 true 时要不同(我会说 20 秒与运行解析器注释器的 3 秒(。 如果这是属性设置为false,则括号与括号的解析时间非常可比,但是解析树仍然非常不同。 对于带括号的文本,如果值为 true,则 POS 为 -LRB-,而 POS 为 CD 表示 false,但在每种情况下,树的一般子结构都是相同的。

就我的语料库而言,括号绝大多数是为了"澄清前因",如本网站所述。 但是,PRN 短语级标签存在于括号中,而不是方括号中,因此即使它们在句子中具有接近相同的功能,树的形成本质上也是不同的。

那么,请解释一下解析时间是如何如此不同的,以及可以做些什么来获得正确的解析? 显然,一种简单化的做法是用括号代替括号,但这似乎不是一个令人满意的解决办法。 是否有任何设置可以为我提供一些缓解? 这是我的代码:

private void execute() {
    Properties props = new Properties();
    props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner");
    props.setProperty("tokenize.options", "normalizeOtherBrackets=false");
    StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
    // 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);
    long start = System.nanoTime();
    ParserAnnotator pa = new ParserAnnotator(DefaultPaths.DEFAULT_PARSER_MODEL, false, 60, new String[0]);
    pa.annotate(document);
    long end = System.nanoTime();
    System.out.println((end - start) / 1000000 + " ms");
    for(CoreMap sentence: sentences) {
        System.out.println(sentence);
        Tree cm = sentence.get(TreeAnnotation.class);
        cm.pennPrint();
        List<CoreLabel> cm2 = sentence.get(TokensAnnotation.class);
        for (CoreLabel c : cm2) {
            System.out.println(c);
        }
    }       
}

是的,这是一个已知(且非常棘手(的问题,不幸的是,没有完美的解决方案。

此类句子的问题主要是由于这些括号结构不会出现在解析器的训练数据中,以及词性标记器和解析器的交互方式。

如果使用选项 normalizeOtherBrackets=true 运行分词器,则方括号将替换为 -LSB--RSB- 。现在,在大多数(甚至可能全部(词性标记器的训练示例中,-LSB-具有POS标记-LRB-,并且-RSB-具有标记-RRB-。因此,尽管考虑到上下文,但POS标记器基本上总是将这些标签分配给方括号。

现在,如果您在解析器之前运行 POS 标记器,则解析器以脱敏化模式运行,这意味着它会尝试根据单个单词的 POS 标签而不是基于单词本身来解析句子。假设您的句子将具有类似于-LRB- NN -RRB-的 POS 序列,解析器会尝试查找生产规则,以便它可以解析此序列。但是,解析器的训练数据不包含此类序列,因此没有任何此类生产规则,因此解析器无法使用此 POS 序列解析句子。

发生这种情况时,解析器将进入回退模式,该模式通过为每个单词的所有其他可能的 POS 标签分配非常低的概率来放宽对词性标签的约束,以便它最终可以根据解析器的生产规则解析句子。然而,这一步需要大量的计算,因此解析这样的句子需要更长的时间。

另一方面,如果您将normalizeOtherBrackets设置为 false ,则它不会将方括号转换为 -LSB--RSB- 并且 POS 标记器会将标签分配给原始[]。但是,我们的训练数据经过预处理,因此所有方括号都被替换,因此[]被视为未知单词,POS 标记器纯粹根据上下文分配标签,这很可能导致 POS 序列是我们的解析器和标记器训练数据的一部分。作为回报,这意味着解析器能够在不进入恢复模式的情况下解析句子,恢复模式要快得多。

如果您的数据包含大量具有此类结构的句子,我建议您不要在解析器之前运行 POS 标记器(通过从注释器列表中删除pos(。这应该仍然会给你更快但仍然可靠的解析。否则,如果您有权访问树库,您还可以使用这些构造手动添加一些树并训练新的解析模型。我不会将normalizeOtherBrackets设置为 false,因为这样您的标记化输入将与解析器和标记器的训练数据不同,这可能会给您带来更糟糕的结果。

最新更新