Вступление

ОБНОВЛЕНИЕ: ознакомьтесь с моим новым введением в статью о НЛП!

Цель этой статьи - представить ключевую задачу NLP, которая является распознаванием именованных сущностей (NER). Цель состоит в том, чтобы иметь возможность извлекать общие сущности в текстовом корпусе. Например, обнаруживать людей, места, лекарства, даты и т. Д. В заданном тексте, таком как электронное письмо или документ.

NER - это техническая часть обширного поля NLP, которое само является частью поля Машинное обучение, которое принадлежит родительскому полю AI .

В этой практической статье мы будем использовать библиотеку Spacy для обучения модели глубокого обучения, основанной на нейронных сетях, для обнаружения сущностей из текстовых данных. Мы также покажем, что часто игнорируется во многих статьях, - это как пометить данные. Мы также сравним глубокое обучение с методом грубой силы с использованием сопоставления с образцом.

В качестве примера мы создадим модель для обнаружения объектов, связанных с нефтью / бензином из этого общедоступного набора данных, который содержит список электронных писем, связанных с нефтяной отраслью. Это чрезмерное упрощение, так как вы хотели бы иметь более общие сущности в реальной жизни, но это предоставит простой пример для NER и покажет пример, в котором сопоставление с образцом может быть лучшим вариантом, чем NER. Итак, чтобы подвести итог, мы собираемся извлечь объекты, связанные с нефтью, из электронных писем.

Мы будем использовать Doccano для маркировки данных, это проект с открытым исходным кодом, который предоставляет удобный пользовательский интерфейс для управления наборами данных, маркировки данных и совместной работы между командами. Вы можете создавать помеченные данные для анализа настроений, распознавания именованных сущностей, текстового обобщения и т. д. Вы можете попробовать демонстрацию аннотаций для получения более подробной информации.

Мы выполним следующее:

  • Прочтите набор данных электронной почты, в каждой строке которого есть электронное письмо.
  • Мы будем маркировать электронные письма сущностью OIL с помощью инструмента маркировки Doccano. Это ручной процесс.
  • Мы сохраним ярлыки в текстовом файле как JSONL.
  • Мы будем использовать модель нейронной сети Spacy для обучения новой статистической модели.
  • Сохраним модель.
  • Мы создадим трубопровод Spacy NLP и будем использовать новую модель для обнаружения невиданных ранее нефтяных объектов.
  • Наконец, мы будем использовать сопоставление с образцом вместо модели глубокого обучения для сравнения обоих методов.

Это будет двухэтапный процесс. Обозначьте данные и обучение модели.

Все данные и записную книжку со всем кодом можно найти в моем репозитории.

Шаг 1. Обозначьте данные

Установка Doccano

Первый шаг - пометить объекты с помощью Doccano.

Если вас не интересует этот шаг, вы можете использовать уже отмеченные данные из здесь и перейти к следующему разделу.

Следуйте инструкциям Doccano, чтобы установить и открыть этот инструмент.

Если вы используете Linux / Mac, я рекомендую использовать образ докера:

  • docker pull doccano/doccano
  • docker container create --name doccano -e "ADMIN_USERNAME=admin" -e "[email protected]" -e "ADMIN_PASSWORD=password" -p 8000:8000 doccano/doccano
  • docker container start doccano

Для Windows просто используйте pip:

  • pip install doccano
  • doccano

Перейдите на http://127.0.0.1:8000/.

Откроется главная страница:

Создать новый проект

В правом верхнем углу нажмите ПРОЕКТЫ:

На следующем экране нажмите Создать:

Введите название и описание. В качестве типа проекта выберите Sequence Labeling, поскольку мы собираемся использовать его для NER вместо классификации текста.

Щелкните "Создать". После закрытия всплывающего экрана выберите название проекта. Откроется страница приветствия проекта.

В меню выберите «Набор данных». В «Действиях» нажмите «Импортировать набор данных».

Во всплывающем окне выберите формат Обычный текст и выберите emails.txt из репозитория. Теперь вы должны увидеть список всего из 23 писем:

Теперь нажмите «Ярлыки» в меню. В «Действиях» выберите Создать ярлык.

Введите OIL в качестве названия ярлыка и ключа 0, затем нажмите «Создать».

Теперь вернитесь к набору данных, в первом элементе нажмите «Аннотировать». Вы должны увидеть первое письмо.

Пришло время ручной работы. Вы можете использовать возможность поиска в браузере для поиска текста о нефти, бензине или нефтепродуктах. Когда вы найдете его, выберите двойным щелчком. Появится всплывающее окно, где вы можете выбрать ярлык, вы также можете нажать кнопку 0. В правом верхнем углу у вас есть навигация, просмотрите 23 письма и пометьте все объекты. Обратите внимание, что некоторые электронные письма могут не содержать каких-либо сущностей, а некоторые могут содержать несколько из них. Важно, чтобы вы ничего не пропустили.

По завершении нажмите «Набор данных» в меню и выберите Действия - ›Экспорт набора данных.

Выберите формат JSONL (текстовая метка). Введите имя файла, например: emails_labeled. Нажмите Экспорт.

Сохраните файл. Теперь вы готовы к шагу 2, обучению модели.

Шаг 2: Обучение модели

Теперь, когда у нас есть обучающий набор, пора приступить к обучению нашей модели с использованием Spacy, встроенного в возможности глубокого обучения. Вы можете открыть Блокнот Jupyter или свой любимый редактор; или проследите по записной книжке в репозитории.

Установить Spacy

Подробные инструкции по установке для вашей платформы см. В документации. При использовании PIP просто выполните:

pip install -U pip setuptools wheel
pip install -U spacy
python -m spacy download en_core_web_sm

Подготовка данных

Сначала давайте прочитаем файл JSONL в формате:

{"id": 15, "text": "....", "meta": {}, "annotation_approver": null, "labels": [[226, 234, "OIL"]]}

import json
labeled_data = []
with open(r"emails_labeled.jsonl", "r") as read_file:
    for line in read_file:
        data = json.loads(line)
        labeled_data.append(data)

Затем давайте преобразуем формат Deccano в формат Spacy. Мы также удалим лишние столбцы и переименуем метки в объекты.

TRAINING_DATA = []
for entry in labeled_data:
    entities = []
    for e in entry['labels']:
        entities.append((e[0], e[1],e[2]))
    spacy_entry = (entry['text'], {"entities": entities})
    TRAINING_DATA.append(spacy_entry)

Обучите модель

Мы используем Deep Learning (NN) и устанавливаем коэффициент отсева 0,3, чтобы предотвратить переобучение.

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

Чтобы избежать переобучения, что означает, что модель «запоминает» обучающие данные и не работает с новыми данными, мы случайным образом отбрасываем некоторые нейроны на каждой итерации, поэтому модель может лучше обобщать.

import spacy
import random
import json
nlp = spacy.blank("en")
ner = nlp.create_pipe("ner")
nlp.add_pipe(ner)
ner.add_label("OIL")
# Start the training
nlp.begin_training()
# Loop for 40 iterations
for itn in range(40):
    # Shuffle the training data
    random.shuffle(TRAINING_DATA)
    losses = {}
# Batch the examples and iterate over them
    for batch in spacy.util.minibatch(TRAINING_DATA, size=2):
        texts = [text for text, entities in batch]
        annotations = [entities for text, entities in batch]
# Update the model
        nlp.update(texts, annotations, losses=losses, drop=0.3)
    print(losses)

Вы должны увидеть, что ошибка уменьшается по мере прохождения итераций, обратите внимание, что иногда она может увеличиваться из-за настройки исключения.

{'ner': 3.7440482430942508}
{'ner': 2.012700471865181}
{'ner': 2.051291773717853}
{'ner': 0.0007268571710379556}
{'ner': 1.8225483010250167}
{'ner': 0.0028021886504119237}
{'ner': 0.0030751793809788803}
{'ner': 1.851928768298534e-06}

Теперь вы можете сохранить модель на диск:

nlp.to_disk("oil.model")

Если вы используете Windows, используйте: nlp.to_disk («/ oil.model»)

Протестируйте модель

Давайте протестируем модель. Для этого мы используем displacy, который отображает объекты в тексте.

from spacy import displacy
example = "service marathon petroleum reduces service postings marathon petroleum co said it reduced the contract price it will pay for all grades of service oil one dlr a barrel effective today the decrease brings marathon s posted price for both west texas intermediate and west texas sour to dlrs a bbl the south louisiana sweet grade of service was reduced to dlrs a bbl the company last changed its service postings on jan reuter"

Давай проверим!

doc = nlp(example)
displacy.render(doc, style='ent')

Вы должны увидеть такой вывод:

Как видите, сущности были обнаружены правильно, как нефть, так и нефть.

Самое замечательное в NER заключается в том, что даже если в тексте есть опечатка, он все равно обнаруживает правильную сущность, например, если я неправильно написал слово "нефть":

Все еще находит совпадение!

Фразовое соответствие

Второй подход - использовать сопоставление шаблонов для поиска определенных ключевых слов и шаблонов в тексте.

Spacy предоставляет сопоставители, которые можно легко использовать для поиска определенных подстрок, цифр и т. д. Мы также можем устанавливать правила на основе тегов части речи.

Это код:

import spacy
# Import the Matcher
from spacy.matcher import Matcher
nlp = spacy.load("en_core_web_sm")
doc = nlp(example)
# Initialize the Matcher with the shared vocabulary
matcher = Matcher(nlp.vocab)
# Add the pattern to the matcher
matcher.add("OIL_PATTERN", None, [{"LOWER": "oil"}], [{"LOWER": "petroleum"}])
# Use the matcher on the doc
matches = matcher(doc)
print("Matches:", [doc[start:end].text for match_id, start, end in matches])

Вы должны увидеть спички, напечатанные в блокноте.

Matches: ['petroleum', 'oil']

Мы можем видеть, как мы также нашли нужный тег, но в этом случае опечатки или похожие слова не обнаруживаются.

Заключение

Мы рассмотрели различные подходы, используемые для распознавания сущностей.

Сопоставление с шаблоном можно использовать в следующих случаях:

  • Атрибуты низкой мощности
  • Общие шаблоны, такие как даты, количества, числа и т. Д. (Regex)
  • Паттерны, встречающиеся в определенных частях речи
  • Когда опечаток не ожидается
  • Структурированные данные

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

  • Атрибуты высокой мощности
  • Вам нужно иметь дело с опечатками (нечеткими совпадениями)
  • Вам необходимо классифицировать новые, никогда не просматриваемые данные.
  • Неструктурированные данные

Эти модели намного мощнее, поскольку они могут принимать решения о вещах, которых раньше не видели. Он может обнаруживать новые объекты без изменения кода.

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

Многие организации тратят много ресурсов на найм талантов и построение сложных моделей для улучшения результатов вместо того, чтобы сосредотачиваться на данных. Хорошая подготовка данных и разработка функций может улучшить производительность модели намного быстрее и лучше, чем алгоритм машинного обучения. Нет ничего более мощного, чем бизнес-аналитик, который разбирается в данных в деталях и немного разбирается в Python!

Поскольку маркировка данных может занять много времени, я рекомендую использовать такие инструменты, как Prodigy, которые сокращают объем ручной работы за счет использования машинного обучения для полуавтоматизации процесса маркировки.

Не забудьте аплодировать, если вам понравилась эта статья, и подписывайтесь на меня или подпишитесь, чтобы получить больше обновления!

Подпишитесь, чтобы получать уведомление, когда я публикую статью, и Присоединяйтесь к Medium.com, чтобы получить доступ к миллионам статей!