TokensRegex - 使用在注释内捕获的组作为Annotate函数的参数

时间:2015-08-12 13:38:58

标签: stanford-nlp

我正在尝试增加与日期相关的开箱即用NER的结果。

例如,短语“上一年”获得NormalizedNER注释“THIS P1Y”,这显然是错误的。
它需要是“PREV_IMMEDIATE P1Y” 实际上,我在“english.sutime.txt”中找到了导致此问题的TokensRegex规则。

我试图通过在下游应用以下提取TokensRegex规则来进行此更正:

{
    ruleType:   "tokens",
    pattern:    ( /the/ /prior/ [ {ner:"DATE"} & {normalized:/THIS (P\d\w.*)/} ]+ ),
    action:     ( Annotate($0, "normalized", "PREV_IMMEDIATE " + $$1.text) ) }

我对此规则有两个问题:

  1. 我找不到合适的语法,将文字字符串与最后一个参数中的捕获组变量组合到Annotate函数中。上面的“操作”字段会导致以下异常:

    edu.stanford.nlp.ling.tokensregex.parser.ParseException:在第34行第72栏遇到“”+“”+“”。 期待以下之一: “)”...... “,”......

    显然,当我使用“+”将字符串附加在一起时,最后一个参数没有正确地转换为String 在最后一个参数中将字符串组合到Annotate函数的正确方法是什么?

  2. 使用“$$ 1.text”作为Annotate的第三个参数给出了以下异常:

    警告:从上一年提取注释时出错 java.lang.ArrayIndexOutOfBoundsException:1

    这应该给我捕获组的文本“(P \ d \ w。*)” 但看起来这个小组似乎并没有被捕获 这是因为在注释中捕获一个组(而不是在令牌文本内部)根本不应该工作吗? 或者我做错了什么?

  3. 一般来说,如果这两个问题无法直接解决,还有什么选择呢? 制作自定义版本的“english.sutime.txt”并使OOTB注释器使用它?

    提前感谢您的帮助!

1 个答案:

答案 0 :(得分:4)

感谢您指出“先前”应被视为指前一次。我们也会将此添加到我们的规则中。为了在SUTime规则中添加“优先”,最简单的方法是改变:

{ pattern: ( /this|the/ /past|previous|last/ ),
  action: Tag($0, "TemporalOp", PREV_IMMEDIATE) }

为:

{ pattern: ( /this|the/ /past|previous|last|prior/ ),
  action: Tag($0, "TemporalOp", PREV_IMMEDIATE) }

如果PREV_IMMEDIATE无效,您可以尝试将其更改为PREV。目的是PREV_IMMEDIATEPREV作为下一个时间表达式的运算符来获取该时间表达式的“上一个”或“过去”,但PREV_IMMEDIATE操作不是经过充分测试这些运算符将在以后的规则中应用:

{ name: "temporal-composite-6b",
  priority: 4,
  pattern: ( ( $REL_MOD ) ( [ $hasTemporal & !{ temporal::IS_TIMEX_SET } ] ) ),
  result: RelativeTime( GetTag($1[0], "TemporalOp"), $2[0].temporal.value )
}

关于TokensRegex语法的问题,

  1. 由于语法实际上不支持完整的java运算符集,因此无法在rules文件中附加+字符串。
  2. 要连接两个字符串,您需要使用do Concat(str1,str2)而不是str1 + str2。有关TokensRegex支持的更多操作,请参阅http://nlp.stanford.edu/nlp/javadoc/javanlp/edu/stanford/nlp/ling/tokensregex/types/Expressions.html

    1. 使用TokensRegex时,有两种类型的捕获组。捕获TokensRegex的组,并使用常规Java模式从匹配的字符串模式捕获组。
    2. /THIS (P\d\w.*)/是一个Java字符串模式。在TokensRegex中,$1用于引用TokensRegex为TokensRegex捕获组1捕获的节点序列。要访问内部捕获组(如来自Java字符串模式的那些),语法$$1为提供访问捕获组的SequenceMatchResult

      要访问这些内容,您需要将matchWithResults设置为TRUE

      {
        ruleType:   "tokens",
        matchWithResults: TRUE,
        pattern:    ( /the/ /prior/ [ {ner:"DATE"} & {normalized:/THIS (P\d\w.*)/} ] ),     
      }
      

      然后,您可以使用(P\d\w.*)访问匹配项 $$0.matchResults[2].normalized.group(1)$$0从TokensRegex获取整个捕获组。 matchResults[2]获取索引2处的标记的matchResults。normalized.group(1)获取与标准化注释对应的Java字符串表达式的捕获组。

      请注意,此模式在SUTime中实际上不起作用,因为在SUTime完成所有规则后,normalized字段由NER填充。