Углубленный анализ
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
- Многометочная классификация с keras
Я также хотел бы поблагодарить тех, кто оказал мне огромную поддержку:
- Лаванья, Стейси и Челси из команды Weights and Biases, которые внимательно рассмотрели эту статью, а также проект.
- Вся команда GDE в Google за предоставление мне кредитов GCP в рамках программы GDE.
- Программа TensorFlow Research Cloud за предоставление мне доступа к облачным TPU, что действительно ускорило выполнение этого проекта.