是否有可能获得一组包含短语的特定命名实体标记

时间:2013-02-04 15:16:47

标签: stanford-nlp named-entity-recognition

我正在使用Stanford CoreNLP解析器来运行一些文本,并且有日期短语,例如“10月的第二个星期一”和“过去的一年”。该库将适当地将每个标记标记为DATE命名实体,但是有没有办法以编程方式获取整个日期短语?并且不只是日期,组织命名实体也会这样做(例如,“国际奥林匹克委员会”可能是在给定文本示例中确定的一个)。

String content = "Thanksgiving, or Thanksgiving Day (Canadian French: Jour de"
        + " l'Action de grâce), occurring on the second Monday in October, is"
        + " an annual Canadian holiday which celebrates the harvest and other"
        + " blessings of the past year.";

Properties p = new Properties();
p.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner, parse");
StanfordCoreNLP pipeline = new StanfordCoreNLP(p);

Annotation document = new Annotation(content);
pipeline.annotate(document);

for (CoreMap sentence : document.get(CoreAnnotations.SentencesAnnotation.class)) {
    for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)) {

        String word = token.get(CoreAnnotations.TextAnnotation.class);
        String ne = token.get(CoreAnnotations.NamedEntityTagAnnotation.class);

        if (ne.equals("DATE")) {
            System.out.println("DATE: " + word);
        }

    }
}

在斯坦福注释器和分类器加载之后,将产生输出:

DATE: Thanksgiving
DATE: Thanksgiving
DATE: the
DATE: second
DATE: Monday
DATE: in
DATE: October
DATE: the
DATE: past
DATE: year

我觉得图书馆必须识别这些短语并将它们用于命名实体标记,所以问题是数据是通过api以某种方式保存和提供的吗?

谢谢, 凯文

3 个答案:

答案 0 :(得分:1)

在邮件列表上讨论后,我发现api不支持这个。我的解决方案是保持最后一个NE的状态,并在必要时构建一个字符串。来自nlp邮件列表的John B.有助于回答我的问题。

答案 1 :(得分:0)

非常感谢,我也会这样做。但是,斯坦福NER API支持classifyToCharOffset(或类似的东西)来获取整个短语。我不知道,也许这只是你想法的实现:D。

答案 2 :(得分:0)

命名实体标记器和词性标记器是CoreNLP管道中的不同算法,似乎API使用者负责集成它们。

请原谅我的C#,但这是一个简单的课程:

    public class NamedNounPhrase
    {
        public NamedNounPhrase()
        {
            Phrase = string.Empty;
            Tags = new List<string>();
        }

        public string Phrase { get; set; }

        public IList<string> Tags { get; set; }

    }

和一些代码来查找所有顶级名词短语及其相关的命名实体标签:

    private void _monkey()
    {

        ...

        var nounPhrases = new List<NamedNounPhrase>();

        foreach (CoreMap sentence in sentences.toArray())
        {
            var tree =
                (Tree)sentence.get(new TreeCoreAnnotations.TreeAnnotation().getClass());

            if (null != tree)
                _walk(tree, nounPhrases);
        }

        foreach (var nounPhrase in nounPhrases)
            Console.WriteLine(
                "{0} ({1})",
                nounPhrase.Phrase,
                string.Join(", ", nounPhrase.Tags)
                );
    }

    private void _walk(Tree tree, IList<NamedNounPhrase> nounPhrases)
    {
        if ("NP" == tree.value())
        {
            var nounPhrase = new NamedNounPhrase();

            foreach (Tree leaf in tree.getLeaves().toArray())
            {
                var label = (CoreLabel) leaf.label();
                nounPhrase.Phrase += (string) label.get(new CoreAnnotations.TextAnnotation().getClass()) + " ";
                nounPhrase.Tags.Add((string) label.get(new CoreAnnotations.NamedEntityTagAnnotation().getClass()));
            }

            nounPhrases.Add(nounPhrase);
        }
        else
        {
            foreach (var child in tree.children())
            {
                _walk(child, nounPhrases);
            }
        }
    }

希望有所帮助!