Как генерировать пользовательские данные обучения для извлечения отношений Стэнфорда
Я обучил пользовательский классификатор для понимания именованных объектов в области финансов. Я хочу создать пользовательские данные обучения, как показано ниже по ссылке 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");
}
}