BERT, XLNet, RoBERTa и т. Д. Для классификации по нескольким меткам - пошаговое руководство

Как специалист по данным, изучавший современные технологии классификации текстов, я обнаружил, что существует не так много простых примеров для адаптации преобразователей (BERT, XLNet и т. Д.) Для многоуровневой классификации… поэтому я решил попробовать на себе и вот оно!

Как дань уважения другим сообщениям блога о классификации текста с несколькими ярлыками, я буду использовать набор данных Toxic Comment Classification Challenge.

К этой публикации прилагается интерактивный Блокнот Google Colab, так что вы можете попробовать это сами. Все, что вам нужно сделать, это загрузить файлы train.csv, test.csv и test_labels.csv в экземпляр. Давайте начнем.

В этом уроке я буду использовать библиотеку трансформаторов Hugging Face вместе с PyTorch (с GPU), хотя это можно легко адаптировать к TensorFlow - я могу написать отдельное руководство для этого позже, если это набирает обороты вместе с учебными пособиями по мультиклассовой классификации. Ниже я буду обучать модель BERT, но я покажу вам, насколько легко можно адаптировать этот код для других моделей трансформаторов по пути.

Импортировать библиотеки

Загрузка и предварительная обработка данных обучения

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

Каждая модель преобразователя требует разных кодировок токенизации - это означает, что способ токенизации предложения и использования масок внимания может отличаться в зависимости от модели преобразователя, которую вы используете. К счастью, библиотека трансформаторов HuggingFace позволяет очень легко реализовать каждую модель. В приведенном ниже коде мы загружаем предварительно обученный токенизатор BERT и используем метод batch_encode_plus для получения токенов, типов токенов и масок внимания. Не стесняйтесь загружать токенизатор, который подходит для модели, которую вы хотите использовать для прогнозирования. например.,

BERT:
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased', do_lower_case=True) 
XLNet:
tokenizer = XLNetTokenizer.from_pretrained('xlnet-base-cased', do_lower_case=False) 
RoBERTa:
tokenizer = RobertaTokenizer.from_pretrained('roberta-base', do_lower_case=False)

Затем мы будем использовать 10% наших обучающих входных данных в качестве набора для проверки, чтобы мы могли отслеживать производительность нашего классификатора во время обучения. Здесь мы хотим убедиться, что мы используем параметр «стратифицировать», чтобы в проверочном наборе не появлялись невидимые метки. Для соответствующей стратификации мы возьмем все метки, которые появляются в наборе данных только один раз, и включим их в обучающий набор. Нам также потребуется создать загрузчики данных PyTorch для загрузки данных для обучения / прогнозирования.

Загрузить модель и установить параметры

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

BERT:
model = BertForSequenceClassification.from_pretrained("bert-base-uncased", num_labels=num_labels)
XLNet:
model = XLNetForSequenceClassification.from_pretrained("xlnet-base-cased", num_labels=num_labels)
RoBERTa:
model = RobertaForSequenceClassification.from_pretrained('roberta-base', num_labels=num_labels)

Параметры оптимизатора можно настроить несколькими способами. Здесь мы используем настраиваемые параметры оптимизации (с которыми я добился большего успеха), однако вы можете просто передать «model.parameters ()», как показано в комментариях.

Модель поезда

Библиотека HuggingFace настроена для мультиклассовой классификации "из коробки" с использованием «категориальной перекрестной энтропии» в качестве функции потерь. Следовательно, выход модели трансформатора будет сродни:

outputs = model(batch_input_ids, token_type_ids=None, attention_mask=batch_input_mask, labels=batch_labels)
loss, logits = outputs[0], outputs[1]

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

outputs = model(batch_input_ids, token_type_ids=None, attention_mask=batch_input_mask, labels=batch_labels)
logits = outputs[0]

Ниже приведен фрагмент кода, который делает именно это. Здесь мы используем «двоичную кросс-энтропию с логитами» в качестве функции потерь. С таким же успехом мы могли бы использовать стандартные «двоичную кросс-энтропию», «потерю Хэмминга» и т. Д.

Для проверки мы будем использовать точность микро F1, чтобы отслеживать эффективность обучения в разные эпохи. Для этого нам нужно будет использовать наши логиты из выходных данных нашей модели, передать их через сигмоидальную функцию (давая нам выходные данные между [0, 1] и порогом их (на 0,50) для генерации прогнозов. Эти прогнозы затем можно использовать для рассчитайте точность по истинным этикеткам.

Альт! Мы готовы к обучению, теперь запустим его ... время моего обучения варьировалось от 20 до 40 минут в эпоху в зависимости от максимальной длины токена и используемого графического процессора.

Прогноз и метрики

Прогноз для нашего тестового набора аналогичен нашему набору проверки. Здесь мы будем загружать, предварительно обрабатывать и прогнозировать тестовые данные.

Выходной DataFrame

Создание фреймворка выходных данных, показывающего предложения и их классификацию.

Бонус - Оптимизация порога для точности Micro F1

Перебор пороговых значений для максимизации точности Micro F1.

Вот и все! Прокомментируйте, если у вас есть вопросы. Вот еще раз ссылка на Блокнот Google Colab, если вы ее пропустили. Если у вас есть личные вопросы, не стесняйтесь обращаться ко мне в LinkedIn или Twitter.

Использованная литература:

Https://electricenjin.com/blog/look-out-google-bert-is-here-to-shake-up-search-queries

Https://github.com/google-research/bert

Https://github.com/huggingface/transformers

Https://pytorch.org/docs/stable/nn.html#bcewithlogitsloss

Https://arxiv.org/abs/1706.03762