1

我正在按照官方说明为财政年度季度(Q1、Q2、Q3 和 Q4 之类的东西)添加自定义 SUTime 规则。

我使用默认的defs.sutime.txtenglish.sutime.txt作为我自己的规则文件的模板。

将以下代码附加到我的之后defs.sutime.txt

  // Financial Quarters
  FYQ1 = {
      type: QUARTER_OF_YEAR,
      label: "FYQ1",
      value: TimeWithRange(TimeRange(IsoDate(ANY,10,1), IsoDate(ANY,12,31), QUARTER))
  }
  FYQ2 = {
      type: QUARTER_OF_YEAR,
      label: "FYQ2",
      value: TimeWithRange(TimeRange(IsoDate(ANY,1,1), IsoDate(ANY,3,31), QUARTER))
  }
  FYQ3 = {
      type: QUARTER_OF_YEAR,
      label: "FYQ3",
      value: TimeWithRange(TimeRange(IsoDate(ANY,4,1), IsoDate(ANY,6,30), QUARTER))
  }
  FYQ4 = {
      type: QUARTER_OF_YEAR,
      label: "FYQ4",
      value: TimeWithRange(TimeRange(IsoDate(ANY,7,1), IsoDate(ANY,9,30), QUARTER))
  }

并将以下代码附加到我的english.sutime.txt

  # Financial Quarters
  FISCAL_YEAR_QUARTER_MAP = {
    "Q1": FYQ1,
    "Q2": FYQ2,
    "Q3": FYQ3,
    "Q4": FYQ4
  }
  FISCAL_YEAR_QUARTER_YEAR_OFFSETS_MAP = {
    "Q1": 1,
    "Q2": 0,
    "Q3": 0,
    "Q4": 0
  }
  $FiscalYearQuarterTerm = CreateRegex(Keys(FISCAL_YEAR_QUARTER_MAP))

  {
    matchWithResults: TRUE,
    pattern: ((/$FiscalYearQuarterTerm/) (FY)? (/(FY)?([0-9]{4})/)),
    result:  TemporalCompose(INTERSECT, IsoDate(Subtract({type: "NUMBER", value: $$3.matchResults[0].word.group(2)}, FISCAL_YEAR_QUARTER_YEAR_OFFSETS_MAP[$1[0].word]), ANY, ANY), FISCAL_YEAR_QUARTER_MAP[$1[0].word])
  }

  {
    pattern: ((/$FiscalYearQuarterTerm/)),
    result: FISCAL_YEAR_QUARTER_MAP[$1[0].word]
  }

我仍然无法正确解析“2020 年第一季度”之类的内容。

如何正确添加解析财政年度季度的规则(例如“Q1”)?

这是我的完整代码:

import java.util.List;
import java.util.Properties;

import edu.stanford.nlp.ling.CoreAnnotations;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.time.*;
import edu.stanford.nlp.util.CoreMap;

public class SUTimeSoExample {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.setProperty("sutime.includeRange", "true");
        props.setProperty("sutime.markTimeRanges", "true");
        props.setProperty("sutime.rules", "./defs.sutime.txt,./english.sutime.txt");

        AnnotationPipeline pipeline = new AnnotationPipeline();
        pipeline.addAnnotator(new TokenizerAnnotator(false));
        pipeline.addAnnotator(new WordsToSentencesAnnotator(false));
        pipeline.addAnnotator(new POSTaggerAnnotator(false));
        pipeline.addAnnotator(new TimeAnnotator("sutime", props));

        String input = "Stuff for Q1 2020";

        Annotation annotation = new Annotation(input);
        annotation.set(CoreAnnotations.DocDateAnnotation.class, "2020-06-01");
        pipeline.annotate(annotation);
        System.out.println(annotation.get(CoreAnnotations.TextAnnotation.class));
        List<CoreMap> timexAnnsAll = annotation.get(TimeAnnotations.TimexAnnotations.class);
        for (CoreMap cm : timexAnnsAll) {
            System.out.println(cm // match
                    + " --> " + cm.get(TimeExpression.Annotation.class).getTemporal() // parsed value
            );
        }
    }
}

请注意,为了避免这个问题defs.sutime.txt,我从 stanford corenlp 模型 JAR 中删除了默认和文件。english.sutime.txt

4

1 回答 1

1

There is a Java code example here:

https://stanfordnlp.github.io/CoreNLP/sutime.html

It should work if you follow that example, mainly building your pipeline in this manner:

props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner");
props.setProperty("ner.docDate.usePresent", "true");
// this will shut off the statistical models if you only want to run SUTime only
props.setProperty("ner.rulesOnly", "true");
// add your sutime properties as in your example
...
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);

and make sure to use version 4.0.0.

You can set ner.rulesOnly to true if you just want to run SUTime without running the statistical models.

You can use one of several properties for ner.docDate or just set the document date in the annotation before running.

于 2020-06-02T03:20:57.473 回答