Данная статья предназначена для тех, кто никогда не работал со Stanford nlp и столкнулся с необходимостью в кратчайшие сроки изучить его и применить.
Данный софт достаточно распространен, и, в частности, наша фирма — БалтИнфоКом — использует эту программу.
Для начала надо понять простую вещь: Stanford NLP работает по принципу аннотирования слов, то есть на каждое слово «навешиваются» одна или более аннотаций, например POS (Part of Speech — часть речи), NER (Named-Entity Recognizing – именованная сущность) и т.д.
Первое, что видит новичок, зайдя на сайт Stanford NLP в раздел "быстрый старт", это следующую конструкцию:
Здесь StanfordCoreNLP – это конвейер, на вход которому подается наш текст, предварительно упакованный в обьект CoreDocument. StanfordCoreNLP, это самый главный и часто используемый объект во всей структуре, с помощью которого происходит вся основная работа.
Сначала задаем параметры в StanfordCoreNLP и указываем, осуществление каких действий нам нужно. При этом все возможные комбинации этих параметров можно найти на официальном сайте по этой ссылке.
Вот пример того, как аннотаторы (parse и depparse) работают вместе:
Если Вам непонятны аннотации над токенами, то на этих сайтах вы найдете их значения: значения связей в предложениях, значения частей речи.
По каждому из этих параметров можно найти дополнительные флаги для более тонкой настройки здесь в разделе «Аnnоtаtоrs».
Данные конструкции задаются, если Вы хотите использовать встроенные модели Stanford NLP, но Вы также можете их задать вручную с помощью метода addAnnotator(Annotator…) или через пополнение параметров перед созданием объекта StanfordCoreNLP.
Теперь о том, какими способами можно извлечь именованные сущности из текста. Для этого в Stanford NLP есть три встроенных класса основанных на регулярных выражениях и один класс, предназначенный для разметки токенов через модель.
Классы, основанные на регулярных выражениях:
Разметка текста через модель с помощью NERClassifierCombiner
Для того, чтобы воспользоваться этим классом, надо сначала иметь или обучить свою модель.
О том, как это сделать можно найти здесь;
После того, как Вы обучили модель, остается только создать NERClassifierCombiner, указав в нем путь к модели, и вызвать метод classify.
Полный список аннотаторов можно посмотреть здесь.
В дополнение к вышесказанному, если Вам требуется использовать Stanford NLP для русского языка, то могу посоветовать зайти сюда. Здесь есть модели для определения частей речи (pos-tagger) и для выявления связей в предложении (dependency parser).
Виды тэггеров, представленных там:
russian-ud-pos.tagger — просто тэггер,
russian-ud-mfmini.tagger — с основным списком morphological features,
russian-ud-mf.tagger — с полным списком morphological features, пример маппинга для которого можно посмотреть здесь.
Данный софт достаточно распространен, и, в частности, наша фирма — БалтИнфоКом — использует эту программу.
Для начала надо понять простую вещь: Stanford NLP работает по принципу аннотирования слов, то есть на каждое слово «навешиваются» одна или более аннотаций, например POS (Part of Speech — часть речи), NER (Named-Entity Recognizing – именованная сущность) и т.д.
Первое, что видит новичок, зайдя на сайт Stanford NLP в раздел "быстрый старт", это следующую конструкцию:
Properties props = new Properties();
props.setProperty("annotators", "tokenize,ssplit,pos,lemma,ner,regexner,parse,depparse,coref");
StanfordCoreNLP pipeline = new StanfordCoreNLP(props);
// create a document object
CoreDocument document = new CoreDocument(text);
// annnotate the document
pipeline.annotate(document);
Здесь StanfordCoreNLP – это конвейер, на вход которому подается наш текст, предварительно упакованный в обьект CoreDocument. StanfordCoreNLP, это самый главный и часто используемый объект во всей структуре, с помощью которого происходит вся основная работа.
Сначала задаем параметры в StanfordCoreNLP и указываем, осуществление каких действий нам нужно. При этом все возможные комбинации этих параметров можно найти на официальном сайте по этой ссылке.
- tokenize – соответственно разбиение на токены
- ssplit – разбиение на предложение
- pos — определение части речи
- lemma – добавление к каждому слову его начальной формы
- ner — определение именованных сущностей, таких как «Организация», «Лицо» и т.д.
- regexner — определение именованных сущностей посредством регулярных выражений
- parse — разбор каждого слова по семантике (род, число и так далее)
- depparse — разбор синтаксических зависимостей между словами в предложении
- coref- поиск упоминания одной и той же именованной сущности в тексте, например «Мария» и «она»
Вот пример того, как аннотаторы (parse и depparse) работают вместе:
Если Вам непонятны аннотации над токенами, то на этих сайтах вы найдете их значения: значения связей в предложениях, значения частей речи.
По каждому из этих параметров можно найти дополнительные флаги для более тонкой настройки здесь в разделе «Аnnоtаtоrs».
Данные конструкции задаются, если Вы хотите использовать встроенные модели Stanford NLP, но Вы также можете их задать вручную с помощью метода addAnnotator(Annotator…) или через пополнение параметров перед созданием объекта StanfordCoreNLP.
Теперь о том, какими способами можно извлечь именованные сущности из текста. Для этого в Stanford NLP есть три встроенных класса основанных на регулярных выражениях и один класс, предназначенный для разметки токенов через модель.
Классы, основанные на регулярных выражениях:
- TokensRegexAnnotator – аннотатор, работающий по правилам – SequenceMatchRules.
Рассмотрим пример маппинга для него, построенного на данных правилах.
ner = { type: "CLASS", value: "edu.stanford.nlp.ling.CoreAnnotations$NamedEntityTagAnnotation" } $EMAIL = "/.*([A-z0-9А-я]+?)(@)([A-z0-9А-я]+?).*/" { ruleType: "tokens", pattern: (([]) ($EMAIL)), action: (Annotate($0, ner, "MAIL")), priority:0 }
В первой строке указываем, какой тип тегов мы будем заполнять в данном шаблоне.
Во второй – создаем переменную, которая по правилам должна начинаться с символа «$» и быть вначале строки.
После этого создаем блок, в котором задаем тип правил. Затем шаблон для сравнения (в нашем случае мы говорим, что нам нужен «[]» — любой токен, после которого идет наша переменная «$EMAIL». После этого задаем действие, в нашем случае мы хотим проаннотировать токен.
Обратите внимание, в примере специально «[]» и «$EMAIL» заключены в круглые скобки, потому что $0 указывает, какую группу захвата мы хотим выделить из найденного шаблона, при этом под группой захвата подразумевается группа, заключенная в круглые скобки. Если задать 0, то во фразе «почта sobaka@mail.ru» все токены будут проаннотированы как «MAIL». Если задать 1(то есть первая группа захвата), то только слово «почта» будет проаннотировано; если 2, то только «sobaka@mail.ru».
Для ситуаций, когда по двум правилам один и тот же токен может быть определен по-разному, можно выставить приоритет правила относительно другого. Например, в случае следующей фразы — «House 25 $», могут быть два противоречащих правила, по одному из которых число 25 будет определено как номер дома, а по второму – как его стоимость. - RegexNERAnnotator – этот аннотатор работает, используя классификатор RegexNERSequenceClassifier.
Маппинг для него выглядит следующим образом
regex1 TYPE overwritableType1,Type2... priority
Здесь regex1 – регулярное выражение в формате TokenSequencePattern.
TYPE – имя именованной сущности.
overwritableType1,Type2… – типы, которые мы можем заменить, в случаях спорной ситуации.
Priority – приоритет для спорных ситуаций, описанных выше.
Обратите внимание, что в данном маппинге все колонки должны быть разделены табом. - TokensRegexNERAnnotator
Данный аннотатор отличается от предыдущего тем, что использует библиотеку TokensRegex для регулярных выражений, ту же, что и первый аннотатор, что позволяет использовать более гибкие правила для сопоставления; а также тем, что может записывать значения тегов, отличных от тега NER.
Маппинг для него составляется по правилам RegexNERAnnotator
Разметка текста через модель с помощью NERClassifierCombiner
Для того, чтобы воспользоваться этим классом, надо сначала иметь или обучить свою модель.
О том, как это сделать можно найти здесь;
После того, как Вы обучили модель, остается только создать NERClassifierCombiner, указав в нем путь к модели, и вызвать метод classify.
NERClassifierCombiner classifier = new NERClassifierCombiner(false, false, serialized_model);
String text = "Some lucky people working in BaltInfoCom Org.";
List<List<CoreLabel>> out = classifier.classify(text);
Полный список аннотаторов можно посмотреть здесь.
В дополнение к вышесказанному, если Вам требуется использовать Stanford NLP для русского языка, то могу посоветовать зайти сюда. Здесь есть модели для определения частей речи (pos-tagger) и для выявления связей в предложении (dependency parser).
Виды тэггеров, представленных там:
russian-ud-pos.tagger — просто тэггер,
russian-ud-mfmini.tagger — с основным списком morphological features,
russian-ud-mf.tagger — с полным списком morphological features, пример маппинга для которого можно посмотреть здесь.