Извлечение многословных именованных сущностей с помощью CoreNLP

Я использую CoreNLP для извлечения именованных сущностей и столкнулся с небольшой проблемой. Проблема заключается в том, что всякий раз, когда именованная сущность состоит из более чем одного токена, например «Хан Соло», аннотатор возвращает «Хан Соло» не как одну именованную сущность, а как две отдельные сущности: «Хан» «Соло». .

Можно ли получить названный объект как один токен? Я знаю, что могу использовать CRFClassifier с classifyWithInlineXML до такой степени, но мое решение требует, чтобы я использовал CoreNLP, поскольку мне также нужно знать номер слова.

Вот код, который у меня есть на данный момент:

    Properties props = new Properties();
    props.put("annotators", "tokenize,ssplit,pos,lemma,ner,parse");
    props.setProperty("ner.model", "edu/stanford/nlp/models/ner/english.conll.4class.distsim.crf.ser.gz");
    pipeline = new StanfordCoreNLP(props);
    Annotation document = new Annotation(text);
    pipeline.annotate(document);
    List<CoreMap> sentences = document.get(SentencesAnnotation.class);
    for (CoreMap sentence : sentences) {
        for (CoreLabel token : sentence.get(TokensAnnotation.class)) {
                System.out.println(token.get(NamedEntityTagAnnotation.class));
        }
    }

Помогите мне, Оби-Ван Кеноби. Ты моя единственная надежда.


person MarkB    schedule 09.03.2014    source источник


Ответы (2)


PrintWriter writer = null;
 try {  
     String inputLine = "Several possible plans emerged from the talks, held at the Federal Reserve Bank of New York" + " and led by Timothy R. Geithner, the president of the New York Fed, and Treasury Secretary Henry M. Paulson Jr.";

     String serializedClassifier = "english.all.3class.distsim.crf.ser.gz";
     AbstractSequenceClassifier<CoreLabel> classifier = CRFClassifier.getClassifierNoExceptions(serializedClassifier);

     writer = new PrintWriter(new File("output.xml"));
     writer.println("<Sentences>");
     writer.flush();
     String output ="<Sentence>"+classifier.classifyToString(inputLine, "xml", true)+"</Sentence>"; 
     writer.println(output);
     writer.flush();
     writer.println("</Sentences>");
     writer.flush(); 
 } catch (FileNotFoundException ex) {
     ex.printStackTrace();
 } finally {
     writer.close();
 }

Я смог придумать это решение. Я записываю вывод в XML-файл "output.xml". Из полученного вывода вы можете объединить непрерывные узлы в xml с атрибутами «PERSON», «ORGANIZATION» или «LOCATION» в одну сущность. И этот формат по умолчанию производит подсчет слов.

Вот снимок вывода xml.

<wi num="11" entity="ORGANIZATION">Federal</wi>
<wi num="12" entity="ORGANIZATION">Reserve</wi>
<wi num="13" entity="ORGANIZATION">Bank</wi>
<wi num="14" entity="ORGANIZATION">of</wi>
<wi num="15" entity="ORGANIZATION">New</wi>
<wi num="16" entity="ORGANIZATION">Yorkand</wi>

Из вышеприведенного вывода вы можете видеть, что слова постоянно распознаются как «ОРГАНИЗАЦИЯ». Итак, эти слова могут быть объединены в одно целое.

person girip11    schedule 23.03.2014
comment
Ба. Я такой глупый. Отличное решение! - person MarkB; 23.03.2014

Я использую одну временную переменную для хранения предыдущего тега Ner и проверяю, совпадает ли текущий тег Ner с temp, он объединит два слова вместе. и итерация идет путем присвоения temp текущему тегу ner.

person HappyCoding    schedule 15.02.2016