Как генерировать пользовательские данные обучения для извлечения отношений Стэнфорда

Я обучил пользовательский классификатор для понимания именованных объектов в области финансов. Я хочу создать пользовательские данные обучения, как показано ниже по ссылке http://cogcomp.cs.illinois.edu/Data/ER/conll04.corp

Я могу пометить пользовательское отношение вручную, но хочу сначала сгенерировать формат данных как conll с моими пользовательскими именованными объектами.

Я также попробовал синтаксический анализатор следующим образом, но он не генерирует данные обучения отношениям, такие как данные Рота и Йиха, упомянутые в ссылке https://nlp.stanford.edu/software/relationExtractor.html.

java -mx150m -cp "stanford-parser-full-2013-06-20 / *:" edu.stanford.nlp.parser.lexparser.LexicalizedParser -outputFormat "penn" edu / stanford / nlp / models / lexparser / englishPCFG.ser.gz stanford-parser-full-2013-06-20 / data / testsent.txt> testsent.tree

java -mx150m -cp "stanford-parser-full-2013-06-20 / *:" edu.stanford.nlp.trees.EnglishGrammaticStructure -treeFile testsent.tree -conllx

Ниже приведен вывод пользовательского запуска отдельно с помощью следующего кода Python

'java -mx2g -cp "*" edu.stanford.nlp.ie.NERClassifierCombiner '\
                '-ner.model classifiers\custom-model.ser.gz '\
                'classifiers/english.all.3class.distsim.crf.ser.gz,'\
                'classifiers/english.conll.4class.distsim.crf.ser.gz,'\
                'classifiers/english.muc.7class.distsim.crf.ser.gz ' \
                '-textFile '+ outtxt_sent +  ' -outputFormat inlineXML  > ' + outtxt + '.ner'

output:

<PERSON>Charles Sinclair</PERSON> <DESG>Chairman</DESG> <ORGANIZATION>-LRB- age 68 -RRB- Charles was appointed a</ORGANIZATION> <DESG>non-executive director</DESG> <ORGANIZATION>in</ORGANIZATION>

Так что NER работает автономно, даже если у меня есть Java-код для проверки.

Вот подробный код для генерации данных отношений

Properties props = new Properties();
        props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner,entitymentions");
        props.setProperty("ner.model", "classifiers/custom-model.ser.gz,classifiers/english.all.3class.distsim.crf.ser.gz,classifiers/english.conll.4class.distsim.crf.ser.gz,classifiers/english.muc.7class.distsim.crf.ser.gz");
        // set up Stanford CoreNLP pipeline
        StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
        // build annotation for a review
        Annotation annotation = new Annotation("Charles Sinclair Chairman -LRB- age 68 -RRB- Charles was appointed a non-executive director");
        pipeline.annotate(annotation);
        int sentNum = 0;

.............. Rest of the code is same as yours

output:
0   PERSON  0   O   NNP/NNP Charles/Sinclair    O   O   O
0   PERSON  1   O   NNP Chairman    O   O   O
0   PERSON  2   O   -LRB-/NN/CD/-RRB-/NNP/VBD/VBN/DT    -LRB-/age/68/-RRB-/Charles/was/appointed/a  O   O   O
0   PERSON  3   O   JJ/NN   non-executive/director  O   O   O

O   3   member_of_board //I will modify the relation once the data generated with proper NER

The Ner tagging is ok now.  
 props.setProperty("ner.model", "classifiers/classifiers/english.all.3class.distsim.crf.ser.gz,classifiers/english.conll.4class.distsim.crf.ser.gz,classifiers/english.muc.7class.distsim.crf.ser.gz,");

Кастом NER проблема решена.

1 ответ

Решение

Эта ссылка показывает пример данных: http://cogcomp.cs.illinois.edu/Data/ER/conll04.corp

Я не думаю, что есть способ сделать это в Stanford CoreNLP.

После того, как вы пометите данные, вам нужно пройтись по предложениям и распечатать токены в том же формате, включая тег части речи и тег ner. Похоже, что в большинстве столбцов есть буква "О".

Для каждого предложения, имеющего отношение, вам необходимо распечатать строку после предложения в формате отношения. Например, эта строка указывает, что предыдущее предложение имеет отношение Live_In:

7    0    Live_In

Вот пример кода для генерации вывода для предложения. Вам нужно будет настроить конвейер для использования вашего ner модель вместо того, чтобы установить ner.model свойство пути вашей пользовательской модели. ВНИМАНИЕ: в этом коде могут быть некоторые ошибки, но он должен показать, как получить доступ к нужным данным из структур данных StanfordCoreNLP.

package edu.stanford.nlp.examples;

import edu.stanford.nlp.ling.*;
import edu.stanford.nlp.pipeline.*;
import edu.stanford.nlp.trees.*;
import edu.stanford.nlp.util.*;

import java.util.*;
import java.util.stream.Collectors;

public class CreateRelationData {

  public static void main(String[] args) {
    // set up pipeline properties
    Properties props = new Properties();
    props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner,entitymentions");
    // set up Stanford CoreNLP pipeline
    StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
    // build annotation for a review
    Annotation annotation = new Annotation("Joe Smith lives in Hawaii.");
    pipeline.annotate(annotation);
    int sentNum = 0;
    for (CoreMap sentence : annotation.get(CoreAnnotations.SentencesAnnotation.class)) {
      int tokenNum = 1;
      int elementNum = 0;
      int entityNum = 0;
      CoreMap currEntityMention = sentence.get(CoreAnnotations.MentionsAnnotation.class).get(entityNum);
      String currEntityMentionWords = currEntityMention.get(CoreAnnotations.TokensAnnotation.class).stream().map(token -> token.word()).
          collect(Collectors.joining("/"));
      String currEntityMentionTags =
          currEntityMention.get(CoreAnnotations.TokensAnnotation.class).stream().map(token -> token.tag()).
              collect(Collectors.joining("/"));
      String currEntityMentionNER = currEntityMention.get(CoreAnnotations.EntityTypeAnnotation.class);
      while (tokenNum <= sentence.get(CoreAnnotations.TokensAnnotation.class).size()) {
        if (currEntityMention.get(CoreAnnotations.TokensAnnotation.class).get(0).index() == tokenNum) {
          String entityText = currEntityMention.toString();
          System.out.println(sentNum+"\t"+currEntityMentionNER+"\t"+elementNum+"\t"+"O\t"+currEntityMentionTags+"\t"+
              currEntityMentionWords+"\t"+"O\tO\tO");
          // update tokenNum
          tokenNum += (currEntityMention.get(CoreAnnotations.TokensAnnotation.class).size());
          // update entity if there are remaining entities
          entityNum++;
          if (entityNum < sentence.get(CoreAnnotations.MentionsAnnotation.class).size()) {
            currEntityMention = sentence.get(CoreAnnotations.MentionsAnnotation.class).get(entityNum);
            currEntityMentionWords = currEntityMention.get(CoreAnnotations.TokensAnnotation.class).stream().map(token -> token.word()).
                collect(Collectors.joining("/"));
            currEntityMentionTags =
                currEntityMention.get(CoreAnnotations.TokensAnnotation.class).stream().map(token -> token.tag()).
                    collect(Collectors.joining("/"));
            currEntityMentionNER = currEntityMention.get(CoreAnnotations.EntityTypeAnnotation.class);
          }
        } else {
          CoreLabel token = sentence.get(CoreAnnotations.TokensAnnotation.class).get(tokenNum-1);
          System.out.println(sentNum+"\t"+token.ner()+"\t"+elementNum+"\tO\t"+token.tag()+"\t"+token.word()+"\t"+"O\tO\tO");
          tokenNum += 1;
        }
        elementNum += 1;
      }
      sentNum++;
    }
    System.out.println();
    System.out.println("O\t3\tLive_In");
  }
}
Другие вопросы по тегам