Углубленный анализ

arXiv Search: Генерация тегов из названий статей с помощью НЛП

Вдохновение и идея

arXiv является хранилищем десятков тысяч открытых статей в области физики, математики, компьютерных наук и так далее. Для практиков машинного обучения, исследователей, специалистов по данным (и всех других должностей, относящихся к областям машинного обучения и науки о данных) arXiv — это дозировка исследований, приложений и теоретических ноу-хау.

Скорость, с которой развивается область машинного обучения, просто нереальна. Каждый день выходят новые газеты. Выдерживать такой темп становится действительно сложно. Более того, в каждой из основных категорий arXiv так много подкатегорий. Например, в категории «Информатика» (cs) есть такие подкатегории, как cs.LG (машинное обучение), cs.CV (компьютерное зрение и распознавание образов), cs.AI (искусственный интеллект), cs.CL (вычисления и язык) и т. д. Эти подкатегории также называются тегами.

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

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

Исходный код проекта доступен здесь.

Размышление над постановкой задачи

Формулировка постановки задачи для проекта машинного обучения — серьезное дело, требующее большого количества мозгового штурма. Я не буду вдаваться в подробности, но если вам интересно, обязательно ознакомьтесь с этим ускоренным курсом Создание проблем от Google. Чтобы начать работу над проектом, мне нужно было начать с определенной постановки задачи. Можно с уверенностью сказать, что данные играют в этом очень важную роль. Итак, я сначала начал искать наборы данных, которые содержат достоверную информацию о документах arXiv, и, к счастью, я нашел один на Kaggle, содержащий кучу информации о документах arXiv с 1992 по 2017 год.

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

Учитывая название статьи arXiv, можем ли мы сгенерировать ее тег(и)?

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

  • Название статьи
  • Тег бумаги

Бумага может иметь несколько тегов. Например, основополагающая статья о Трансформерах, а именно Внимание — это все, что вам нужно, имеет два тега: cs.CL и cs.LG. Учитывая этот аспект, постановку задачи можно смоделировать как задачу классификации текста с несколькими метками.

Были и другие особенности (всего их было 9):

  • Бумажный идентификатор
  • Дата подачи
  • День
  • Месяц
  • Год
  • Ссылка на бумагу
  • Аннотация статьи
  • Имя автора (ов)

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

Набор данных поставляется в формате JSON. Когда я загрузил его с помощью pandas, это выглядело примерно так:

Как видите, если бы я хотел получить какую-либо информацию из набора данных, этот формат на самом деле не помог бы. После нескольких попыток разобраться с этим я смог привести набор данных к следующему виду:

Именно так, как это нужно для нашей постановки задачи!

После дальнейшего изучения я узнал, что в оспариваемом наборе данных присутствует в общей сложности 41 000 названий статей и 2 606 уникальных тегов (некоторые из них одиночные, а некоторые — множественные). Когда я начинаю проект, я предпочитаю начинать с простого, поэтому я решил оставить набор данных в топ-100 тегов. После фильтрации результатов я пришел к следующему распределению первых 10 тегов:

Как видите, это явный признак дисбаланса классов (подробнее об этом позже). Важно отметить, что неожиданным аспектом проекта также была проблема с дублирующимися записями, с которой мне пришлось столкнуться.

После того, как я узнал о типах статей, мне стало интересно узнать, влияет ли длина названия статьи на определение ее тегов; Корреляция Пирсона, разумеется, была нулевой. Прежде чем мы перейдем к следующему разделу, я также хочу показать вам следующий график, показывающий распределение длин заголовков (правда, это гладкое распределение?):

Решение основных проблем с данными

Во-первых, отфильтрованный набор данных был сильно несбалансирован. Я решил это следующим образом:

  • Сначала я получил веса (количество экземпляров, с которыми связаны определенные метки) классов.
  • Затем я использовал эти веса, пока тренировал модели. Это позволяет взвешивать классы меньшинств выше, чем классы большинства.

Следующая проблема возникла, когда я попытался выполнить бинаризацию по меткам. Взгляните на первые десять ярлыков:

Обратите особое внимание на двойные кавычки. Для них всякий раз, когда я пытался использовать MultiLabelBinarizerкласс scikit-learn, это происходило неправильно. На самом деле мне потребовалось некоторое время, чтобы понять это, и, наконец, я наткнулся на эту тему на StackOverflow, которая помогла мне решить эту проблему (спойлер: мне пришлось использовать literal_eval). После того, как я преодолел эту проблему, я смог правильно представить теги с точки зрения 0 и 1 (ниже представлена ​​мультибинарная версия первых десяти ярлыков):

Для названий статей я использовал стандартные шаги предварительной обработки данных:

  • Представление заголовков во всех строчных буквах
  • Удаление специальных символов/пробелов
  • Токенизация
  • Удаление стоп-слов

К этому моменту я был готов заняться машинным обучением.

Эксперименты с моделями машинного обучения: от простого к сложному

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

  • Время обучения модели
  • Производительность модели на проверочном наборе
  • Скорость вывода
  • Размер модели

Как некоторые из вас, возможно, уже знают, выбор наилучшей архитектуры модели также требует большого количества экспериментов. Проблема в том, что вы можете упустить хорошую модель, если не будете должным образом отслеживать свои эксперименты. Я делегирую эту ответственность Weights and Biases. Он хорошо работает с рядом популярных фреймворков машинного обучения Python, таких как TensorFlow, PyTorch, Scikit-Learn, XGBoost и т. д. Кроме того, требуется всего несколько строк кода для настройки, чтобы Weight and Biases могли начать отслеживать ваши эксперименты.

Для этого проекта я начал с простых моделей, таких как Наивный байесовский анализ, Логистическая регрессия и т. д. Для этого я использовал проверенный временем Scikit-Learn. Два наиболее важных графика из этих экспериментов вы можете увидеть здесь. Вы можете увидеть их на следующем рисунке:

Weights and Biases также предоставили мне исчерпывающий отчет, который позволяет легко делиться своими выводами между командами:

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

  • на основе CNN
  • на базе ГРУ
  • Двунаправленный на основе LSTM

Вы можете найти резюме экспериментов, которые я провел с ними, в приведенных ниже диаграммах:

Как обычно, в комплекте была таблица:

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

Выяснив наиболее производительную модель (CNN) из набора экспериментов, я использовал ее, чтобы сделать прогнозы для некоторых последних названий статей. Вот снимок:

Неплохо!

Weights and Biases дает вам возможность регистрировать много другой информации, которую вы, возможно, захотите добавить на свою панель инструментов. В этом случае я хотел посмотреть, как модель ведет себя на некоторых выборочных данных проверки во время обучения, и я хотел зарегистрировать это в удобном формате на панели инструментов «Вес и смещения». Я смог сделать это, написав несколько строк кода:

# A custom callback to view predictions on the above samples in real-time
class TextLogger(tf.keras.callbacks.Callback):
def __init__(self):
super(TextLogger, self).__init__()
def on_epoch_end(self, logs, epoch):
samples = []
for (title, true_label) in sample_paper_titles.items():
predicted_label = generate_predictions(self.model, title)
sample = [title, predicted_label, true_label]
samples.append(sample)
wandb.log({“text”: wandb.Table(data=samples,
columns=[“Text”, “Predicted Label”, “True Label”])})

Мне очень понравилось, чего я смог добиться с помощью приведенного выше фрагмента:

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

Для обучения моделей на основе GRU и LSTM требовалось значительное количество времени (но не дней). Итак, я решил запустить их с помощью Cloud TPU и был поражен ускорением. Найти соответствующий блокнот можно здесь.

Дальнейшие действия

Среди моделей глубокого обучения, которые я пробовал, я уверен, что не тренировал их достаточно усердно. Я определенно собираюсь обучить модель на основе CNN и модель на основе LSTM для больших эпох (текущее количество эпох — 10). Есть куча других гиперпараметров, с которыми я не экспериментировал — размер встраивания, максимальное количество слов, допустимых в токенизаторе, максимальная длина последовательности и так далее. С этой целью я также хотел бы включить рефераты статей в набор данных, чтобы увидеть, улучшаются ли прогнозы. Конечно, за это придется заплатить — усложнение модели, увеличение стоимости вычислений и так далее.

Проверка гиперпараметров значительно упрощает правильное управление большим объемом экспериментов по настройке гиперпараметров. Я определенно собираюсь использовать его в следующей итерации этого проекта.

Я также рад попробовать модели BERT Hugging Face для улучшения производительности классификации. Мой окончательный план состоит в том, чтобы представить окончательную модель как REST API, чтобы ее могли использовать другие разработчики.

Ссылки и благодарности

Ниже приведены некоторые из ссылок, которые очень помогли мне в достижении этой стадии проекта:

Я также хотел бы поблагодарить тех, кто оказал мне огромную поддержку:

  • Лаванья, Стейси и Челси из команды Weights and Biases, которые внимательно рассмотрели эту статью, а также проект.
  • Вся команда GDE в Google за предоставление мне кредитов GCP в рамках программы GDE.
  • Программа TensorFlow Research Cloud за предоставление мне доступа к облачным TPU, что действительно ускорило выполнение этого проекта.