Введение

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

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

Вы можете найти полный код этой статьи с пометкой релиз 1.0.0 по адресу: https://github.com/ceesroele/toxic_spans.

Чтобы скачать этот релиз:

git clone https://github.com/ceesroele/toxic_spans.git —-branch v1.0.0

Категоризация пролетов

span — это фрагмент текста, который мы можем пометить как относящийся к какой-либо категории. Текст может состоять из нескольких диапазонов, которые могут иметь разные метки. Промежутки аналогичны Распознаванию именованных объектов (NER).

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

SpaCy содержит SpanCategorizer, начиная с версии 3.1. Это элемент — кратко названный spancat — в конвейере spaCy, который может обнаруживать интервалы, для которых он был обучен.

Набор данных о токсичных интервалах

Мы используем набор данных из задачи 5 SemEval2021. Вы можете найти описание задачи и обсуждение результатов для разных участников в SemEval-2021 Task 5: Toxic Span Detection (2021) John Pavlopoulos et al¹. Набор данных и базовый код доступны на github.

Набор данных содержит около десяти тысяч постов с аннотациями для токсичных спанов. Эти аннотации состоят из списка всех индексов символов поста, которые являются частью токсичного спана.

Пример из файла CSV, содержащего данные:

«[11, 12, 13, 14, 16, 17, 18, 19, 20]», ты один больной щенок.

Индексы символов от 11 до 20 относятся к «больному щенку».

В общем, о наборе данных:

  • Многие посты содержат один спан
  • Подавляющее большинство спанов состоит из одного слова, например. "идиот".

Обратите внимание, что существует только одна категория (токсичные) и идентификация спанов осуществляется по символам, поэтому, хотя теоретически возможно иметь два частично перекрывающихся токсичных спана, на практике в нашем наборе данных этого не происходит. Одним из результатов является то, что можно рассматривать проблему как проблему NER, а не как проблему диапазона. Собственно, именно так было реализовано обнаружение токсичных спанов в примере сценария spaCy NER, предоставленном с набором данных.

Проект

Наша цель — создать трубу spaCy, которая выявляет недопустимые спаны в тексте. Для этого мы должны обучить модель, используя наш набор данных. После обучения модели мы хотим ее оценить. Если это нас удовлетворит, мы развернем нашу модель.

Вот наши шаги:

  1. Загрузите файлы данных CSV (уже разделенные на наборы для обучения, разработки и тестирования)
  2. Преобразуйте данные в формат, который можно использовать для обучения.
  3. Тренироваться
  4. Оценивать
  5. Разверните полученную модель

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

Мы пойдем вторым путем и определим проект spaCy для наших шагов. За основу возьмем project.yml из экспериментального проекта NER-spancat. Этот проект предоставляет NER для индонезийского языка с использованием функций SpanCategorizer.

Скачать файлы данных

В нашем файле проекта мы определяем местоположение наших активов, то есть данных, которые мы ищем. Здесь мы получаем все файлы из пути в репозитории в github и помещаем их в подкаталог или место назначения активы.

Давайте загрузим активы:

Мы видим, что «1 актив(ы)» состоит из трех файлов CSV. Это те, которые были по пути SemEval2021/data в репозитории, указанном выше.

Конвертировать

Теперь, когда у нас есть файлы данных, нам нужно преобразовать данные в формат, подходящий для обучения. Здесь мы объединяем список индексов и текстовых строк в строках наших трех CSV-файлов в Doc объектов с определенными интервалами.

Эти объекты Doc мы объединяем в один объект DocBin, который сохраняем в файл в пользовательском двоичномspacy формате.

Мы вызываем эти методы из файла с именем make_corpus.py. Обратите внимание, что мы преобразовываем исходные имена файлов данных в train, dev и eval.

В нашем определении проекта мы определяем команду из вызова вышеприведенного make_corpus.py:

Чтобы фактически создать корпус файлов spacy из ресурсов CSV, выполните следующие действия:

Тренироваться

Теперь у нас есть наборы данных train и dev в формате, который мы можем обрабатывать. Чтобы на самом деле обучить модель распознавать токсичный интервал с использованием этих данных, нам нужно сначала настроить такую ​​модель и некоторые параметры для нашего процесса обучения.

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

Единственное изменение по сравнению с настройками по умолчанию, которые мы делаем в виджете выше, заключается в том, что мы проверяем spancat, чтобы включить канал SpanCategorizer. Обратите внимание, что выбор accuracy для «оптимизировать для» приведет к использованию большой языковой модели.

Отображаемая часть сгенерированной конфигурации является лишь частью всего файла.

Копируем содержимое настроенного виджета и вставляем в файл configs/base_config.cfg. Затем мы заполняем его всеми значениями по умолчанию и сохраняем результат как configs/config.cfg с помощью следующей команды:

Обратите внимание на следующий шаг:

Значение по умолчанию spans_key для SpanCategorizer равно sc . Вы можете использовать это значение по умолчанию, что избавит вас от некоторых дополнительных шагов, которые я сделал ниже. Тем не менее, я думаю, что это хорошая практика, позволяющая каждому приложению, добавляющему спаны, в данном случае токсичные спаны, устанавливать свои собственные spans_key, так как это позволяет вам смешивать спаны из разных источников. Например. SpanRuler SpaCy использует по умолчанию spans_key=ruler.

Мы делаем несколько модификаций в нашем новом configs/config.cfg:

  • Мы устанавливаем для нашего spans_key значение txs, чтобы не использовать значение по умолчанию sc.
  • Мы определяем размеры для ngrams для Suggester всего от 1 до 8. ( Suggester выходит за рамки этой статьи. Для получения информации см. spaCy SpanCategorizer документация.)
  • Мы определяем столбцы для представления оценок во время обучения, исключая столбцы для scspans_key по умолчанию и включая столбцы для нашего нового определенного txsspans_key.

В нашем файле проекта мы определяем, как запустить наше обучение. Самое главное, мы обращаемся к нашему файлу конфигурации ( configs/${vars.config}.cfg , где vars.config было определено как «config»), используем созданный нами corpus/train.spacy для базового обучения, а corpus/dev.spacy для набора для разработки.

Теперь давайте начнем процесс обучения и будем следить за результатами по мере выполнения обучения.

Мы видим, что у нас самая высокая оценка — равная spans_txs_f — 0,57. Модель, которая использовалась для получения наилучшего результата, сохранена в ./training/model-best.

Оценивать

Как мы уже видели во время обучения, стандартная метрика, используемая для оценки пролетов, — Точность — Отзыв — F1.

F1 объединяет точность и полноту в единую меру, которая охватывает оба свойства.

Точность = TruePositives / (TruePositives + FalsePositives)

Отзыв = TruePositives / (TruePositives + FalseNegatives)

F1 = (2 * Точность * Отзыв) / (Точность + Отзыв)

Стандартный счетчик для spaCy SpanCategorizer вычисляет эти показатели по всем токенам. Поскольку мы хотим сравнить наш результат с опубликованными оценками участников задания SemEval2021, где использовалась оценка на основе символов, мы также хотим создать оценку F1 на основе символов для нашей оценки. Это означает, что в «Hello idiot world!» мы считаем idiot не как 1 TruePositive, а как 5 TruePositives, то есть по одному на каждый символ токена idiot. Между этими двумя методами расчета существует небольшая числовая разница.

В нашем файле проекта мы определяем, как запустить нашу оценку. Самое главное, мы используем наш созданный corpus/eval.spacy для предоставления данных для оценки модели, используем training/best-model и запускаем сценарии для стандартных оценок на основе токенов и пользовательских оценок на основе символов.

Приступаем к оценке:

Внизу мы видим, что наша оценка F1 на основе символов: F1 = 63.01, что на один процентный пункт ниже, чем оценка F1 на основе токенов.

Как это соотносится с результатами участников SemEval2021 Task 5: Toxic Span Detection? Давайте посмотрим:

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

Разверните полученную модель

Для наглядности достаточно просто загрузить лучшую модель из каталога, в котором она была сохранена в процессе обучения, в training/model-best.

Сценарий ниже использует обученную модель и отображает предсказанные промежутки с помощью displaCy.

Запустив приведенный выше скрипт в блокноте Jupyter, мы получим:

Хорошо, это работает!

Заключение

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

Интерпретация результатов не входила в рамки статьи. О нем будет рассказано в следующей статье.

Рекомендации

[1] «SemEval-2021 Task 5: Toxic Spans Detection (2021), John Pavlopoulos et al.

История обновлений

8 мая 2022 г.: ссылка на часть 2:Пользовательская оценка пролетов в spaCy

25 августа 2022 г.:
1. Добавлена ​​ссылка на релиз клона v1.0.0 вверху статьи.

2. Объяснил, почему я использую пользовательский spans_key, а не sc по умолчанию SpanCategorizer.

6 сентября 2022 г .:

Отображение промежутков теперь использует displaCy. Удалена ссылка на пользовательский код для отображения спанов.