Научитесь создавать приложение Tweet Generator с нуля с помощью кода для загрузки данных из Twitter, обучения модели GPT-2 в Google Colab и развертывания на AWS

Быстрые ссылки

Приложение: http://botbaby.in/
GitHub: https://github.com/nikhilno1/bot-baby

Оглавление:

- Предпосылки и цель
- Общая картина
- Создание набора данных
- Модельное обучение
- Развертывание на AWS
- Front-end
- Аналитика
- Результаты
- Проблемы

Предпосылки и цель

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

Я также стремился получить реальный опыт MLOps, который, как я полагаю, поможет мне в моем следующем концерте. У меня все еще оставалось 3 месяца до годичного перерыва в середине карьеры. Так как времени было не так много (так как я тоже буду искать работу), я хотел выбрать задачу, которая не слишком сфокусирована на алгоритме машинного обучения, но позволила бы мне потратить достаточно времени на обучение развертыванию производственных моделей машинного обучения. в масштабе.

Я решил начать с создания приложения-генератора твитов для левого (LW) и правого (RW) индийского твиттера. Идея приложения состоит в том, чтобы подчеркнуть поляризацию и язык, используемый обоими лагерями. Как я понял, преимущества начала с этого заключались в следующем:

  1. Позволяет создать основу для загрузки / потоковой передачи данных Twitter.
  2. Разработайте языковую модель, которую я позже смогу использовать для других последующих задач.
  3. Обучение модели Light on ML позволило мне создать полное приложение примерно за месяц.
  4. Полный жизненный цикл MLOps, включая контроль версий для данных и модели.
  5. Добавьте возможности поиска с помощью Elasticsearch, чтобы получить другую интересную информацию.
  6. Создайте основу для решения других проблем (фальшивые новости / тенденции, BOTs, сообщения ненависти и т. Д.)

Четко обозначив свои цели, я начал работать над этим и создал приложение примерно за 3 недели.

Давайте теперь рассмотрим все детали.

Большая картинка

Вот краткий снимок всех строительных блоков, которые мы рассмотрим.

Создание набора данных

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

Теперь получение списка учетных записей LW & RW может быть небольшой проблемой, потому что эта информация нигде публично не представлена. Более того, все считают себя центристами. :)

Сначала я подумал о создании какого-то социального графа или алгоритма кластеризации, но потом обнаружил, что мне не нужно делать ничего такого сложного. Вот что я в итоге сделал:

  1. Я начал с небольшого количества учетных записей, которые довольно часто помечаются как LW или RW с другой стороны.
  2. Я использовал собственный механизм рекомендаций Twitter, функцию «Подобно X», чтобы найти больше подобных инструментов.
  3. Благодаря этому я составил список из 35-40 пользователей для каждой стороны, я называю их лидерами.
  4. Затем я скачал список подписчиков для всех лидеров.
  5. Я объединил список подписчиков и отсортировал их по частоте.
  6. Идея состоит в том, что любой, кто следует за большинством «лидеров», скорее всего, принадлежит к тому же лагерю.
  7. Таким образом, после удаления общих учетных записей, фигурирующих в обоих списках, я получил список из 150 тыс. Самых популярных аккаунтов в Твиттере для каждой из сторон.
  8. Затем я загружал твиты для всех этих пользователей, что становилось моим набором данных.

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

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

Примечание. Tweepy против GetOldTweets3

Tweepy: 7 дней, 18 000 твитов за 15-минутное окно. 3200 последних твитов, подробная информация по каждому твиту.

GetOldTweets3: без авторизации, меньше информации, извлекает старые твиты

Шаги по загрузке данных твитов:

  1. Используя tweepy, я сначала загрузил все идентификаторы подписчиков. Преимущество получения идентификаторов подписчиков вместо имен пользователей - ускорение в 15 раз. Ограничение скорости для идентификаторов составляет 45000 против 3000 для имен пользователей.
  2. Когда у меня есть все идентификаторы подписчиков, я их объединяю, сортирую в порядке убывания и, наконец, дедуплицирую их.
  3. Затем я конвертирую идентификаторы в имена пользователей с помощью HTTP-запроса Twitter GET, не имеющего ограничений по скорости. Этот шаг необходим, поскольку GetOldTweets3 работает с именами пользователей, а не с идентификаторами.
  4. Наконец, используя GetOldTweets3, я загружаю твиты для каждого пользователя, начиная с 2014 года. Почему именно 2014? Что ж, это был год выборов, и примерно в это время многие люди начали проявлять активность в твиттере.
  5. После загрузки достаточного количества данных я выполняю предварительную обработку текста для удаления гиперссылок, неанглийских символов (поскольку моя языковая модель понимает только английский) и очень коротких твитов. Я собираю все эти твиты в один текстовый файл (отдельный для LW и RW), который дает мне окончательный набор данных для обучения.

Модельное обучение (в Google Colab)

Когда я начал работать над этим приложением, я сначала начал с обучения моей собственной языковой модели с нуля. Я обучил модель GPT-2 на TPU в Google Cloud. Но результаты оказались не такими увлекательными, как с Блокнотом Макса Вульфа. Это сработало прямо из коробки, давая фантастические результаты, поэтому я придерживался его. Чтобы облегчить тренировочную боль, я даже подписался на подписку Colab Pro, которая является такой выгодой. На день обучения на TPU я потратил более 100 долларов, но Colab Pro стоит мне 10 долларов в месяц. Я призываю всех воспользоваться им. Это дает вам больше таймаутов и RAM.

Моя тетрадь для тренировки присутствует здесь. Он полностью идентичен оригинальной работе Макса. Я использую модель 355М GPT-2. В зависимости от размера моего набора данных я тренировался от 2000 до 6000 шагов, пока не увидел, что средние потери снижаются. Для моего набора данных для обучения размером около 300 МБ (на каждую сторону) я тренировался за 6000 шагов.

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

Развертывание на AWS

Мой первоначальный план состоял в том, чтобы развернуть производственную версию недавно выпущенного Google AI Platform Pipelines. Это просто похоже на универсальный продукт для выполнения ваших MLOps. Однако, когда я наткнулся на этот блог, в котором были подробные инструкции по развертыванию на AWS, я подумал, почему бы мне не сделать это в первую очередь. Когда вы работаете в одиночестве, важно получать частые дозы мотивации. Нет ничего лучше для мотивации, чем как можно раньше отправить приложение. Поэтому я решил сначала развернуть его на AWS, а затем позаботиться о масштабном развертывании с правильным рабочим процессом на конвейерах платформы AI.

Как также объясняется в блоге, мы не можем полностью отказаться от сервера, поскольку каждая модель близка к 1,5 ГБ, поэтому мне нужно как минимум 3 ГБ только для моделей. Кроме того, мне нужно выполнить пакетный вывод, для которого мне нужен экземпляр графического процессора.

Вот как выглядит текущая архитектура развертывания:

Хостинг:

Веб-сайт статически размещен на Amazon S3, что является действительно дешевым и быстрым способом представить ваш сайт в мире.

Шлюз API:

Это создает конечную точку API, которая будет получать входящий HTTP-запрос от вашего интерфейсного приложения и вызывать настроенную функцию Lambda.

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

Лямбда-функция:

Функция Lambda получает HTTP-запрос GET от шлюза API и выполняет следующие действия:

  1. Убедитесь, что приглашение уже существует в DynamoDB. Если да, то прочтите запись и верните ответ. Эта операция занимает несколько миллисекунд.
  2. Если это новое приглашение, добавьте запрос в очередь SQS FIFO и запустите экземпляр EC2 g4dn.xlarge.
  3. После запуска экземпляра продолжайте опрашивать DynamoDB, чтобы проверить, доступно ли новое приглашение для чтения. В этом случае он считывает вновь добавленную запись и возвращает ответ шлюзу API.
  4. Лямбда-функция выполняет дополнительный шаг перед возвратом ответа. Он выбирает тональность большинства сгенерированных твитов и возвращает только те. Например, если база данных возвращает 10 твитов, из которых 7 положительные, 2 отрицательные и 1 нейтральный. Затем лямбда-функция вернет 7 положительных твитов, поскольку это указывает на мнение большинства. Помните, что создание языка является вероятностным по своей природе, поэтому имеет смысл отображать вывод большинства.

Как и в случае с конечной точкой API, нам также необходимо увеличить тайм-аут для Lambda.

Совет: используйте TestEvent для проверки вашей лямбда-функции. Вы можете настроить тестовое событие, как показано ниже:

{
 “queryStringParameters”: {
 “model”: “left”,
 “prompt”: “Test prompt”,
 “num_samples”: “20”,
 “length”: “80”,
 “temperature”: “0.7”,
 “top_p”: “0.9”,
 “top_k”: “40”
 }
}

Простая служба очереди (SQS):

Чтобы сериализовать входящие HTTP-запросы, я использую очередь SQS FIFO. Функция Lambda помещает входящий запрос в эту очередь и запускает экземпляр EC2 GPU. Экземпляр графического процессора при запуске читает из этой очереди и запускает логический вывод один за другим. Это позволяет мне обрабатывать одновременные запросы с одним экземпляром EC2 очень рентабельно.

Экземпляр графического процессора EC2:

Для логического вывода я использую недавно запущенный и экономичный экземпляр G4 (если быть точным, g4dn.xlarge). Инстансы G4 предоставляют графические процессоры NVIDIA T4 последнего поколения по цене 0,58 доллара в час за хосты по запросу. Стоимость может быть дополнительно снижена за счет использования спотовых инстансов. Перед использованием экземпляра G4 необходимо поднять запрос на обслуживание для увеличения лимита виртуальных ЦП.

В исходном коде автор запускает скрипт Python на экземпляре EC2. Однако это означало дополнительные 15 секунд для загрузки модели в память для каждого вывода. Я изменил это, чтобы вместо этого запускать веб-приложение (на основе Starlette). Ниже показано все, что происходит в инстансе EC2 от начала до конца.

  1. Лямбда-функция запускает экземпляр EC2.
  2. Два отдельных веб-приложения запускаются (по одному для каждой модели) как часть запуска системы (как служба systemd) и начинают прослушивать порты 8081 и 8082.
  3. При запуске запускается другая служба, которая отслеживает очередь SQS. Всякий раз, когда поступает новый запрос, эта служба обрабатывает его и вызывает соответствующий запрос GET, используя CURL, который запускает логический вывод в серверном веб-приложении.
  4. Серверное веб-приложение после получения запроса вызывает API GPT2 для создания пакета 20 твитов.
  5. Затем он выполняет очистку, чтобы сохранить наиболее разумные твиты. Сначала он удаляет ненужные символы, такие как новые строки и кавычки. Затем он удаляет последнее предложение, которое, вероятно, будет неполным, с помощью функции NLTK sent_tokenize (). Иногда сгенерированные твиты содержат повторяющуюся последовательность слов или предложений, поэтому удаляются твиты с меньшим количеством уникальных слов.
  6. Затем веб-приложение использует сервис AWS Comprehend для анализа тональности оставшихся твитов. Он сохраняет 10 самых популярных твитов. Идея состоит в том, что твиты с высокими баллами в любой из категорий (положительные, отрицательные или нейтральные) имеют тенденцию быть более связными, чем твиты с более равномерно распределенными баллами.
  7. Затем 10 самых популярных твитов сохраняются в DynamoDB в отсортированном порядке.
  8. Если в течение более 15 минут не поступает новый запрос, инстанс EC2 отключается для экономии средств.
  9. Как часть процесса завершения работы, вызывается сценарий, который обновляет вновь добавленные запросы к файлу на S3. Это используется для обеспечения функции автозаполнения в пользовательском интерфейсе.

Внешний интерфейс

Интерфейс разработан с использованием HTML, CSS и Javascript. Чтобы воспроизвести пользовательский интерфейс Twitter, находкой стала книга Энди Леверенца Let's Build: With Tailwind CSS - Tweet. Он предоставил базовый интерфейс для отображения одного твита, который позже я мог расширить (с некоторой помощью от Manan), чтобы отображать твиты бок о бок.

Как упоминалось ранее, веб-сайт статически размещен на Amazon S3.

Автозаполнение:
Учитывая, что вывод нового приглашения занимает от 30 до 60 секунд, тогда как если пользователь вводит существующее приглашение, результаты достигаются примерно за 250 мс, имеет смысл поощрять пользователям больше использовать существующие подсказки. Поэтому стало важным добавить функцию автозаполнения, чтобы пользователь мог выбрать один из списка вместо того, чтобы вводить свой собственный.

Я рассмотрел несколько сложных решений (с использованием Elasticsearch или AWS Cloud Search), прежде чем реализовывать что-то чрезвычайно простое.

Поскольку мой веб-сайт размещен на S3, я изменил свой интерфейсный код, чтобы читать файл «подсказок» из S3. Этот файл содержит список всех существующих подсказок. После того, как пользователь выполняет вывод для нового приглашения, всякий раз, когда экземпляр завершает работу, этот файл приглашения на S3 обновляется. Есть небольшая задержка, но в остальном это простое решение отлично работает.

Аналитика

Я хотел получить статистику использования и предоставить пользователям возможность оставлять отзывы о приложении.

Вот некоторые вещи, которые я добавил для этого:

  1. В DynamoDB добавлен счетчик «посещенных», чтобы каждое чтение записи запускало (атомарное) приращение этого счетчика. Я могу использовать это для отображения популярных запросов.
  2. Включен сбор подробных метрик маршрута на конечной точке API. Я могу использовать это, чтобы получить более подробную информацию о количестве посетителей, местоположении и т. Д. В AWS.
  3. Интегрирован с Google Analytics для получения более подробной статистики использования
  4. Интегрирован с mopinion для получения отзывов пользователей.

Для обоих (3) и (4) вам просто нужно скопировать несколько строк кода в свой HTML, который они предоставляют.

Результаты

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

“temperature”: “0.7”,
 “top_p”: “0.9”,
 “top_k”: “40”

Где,
temperature: чем выше температура, тем безумнее текст.
top_k: ограничивает сгенерированные предположения до верхних k предположений
top_p: выборка ядра: ограничивает сгенерированные предположения кумулятивной вероятностью.

Примеры нескольких результатов:

Вызовы

В этом разделе перечислены некоторые проблемы, с которыми я столкнулся на этом пути. Надеюсь, это поможет кому-то, кто сталкивается с подобными проблемами.

  1. Установите данные NLTK с помощью команды nltk.download(‘punkt’)
  2. Код app.py взят из gpt-2-cloud-run. Я столкнулся с ошибкой сборки при установке пакета ujson. Ошибка возникла из-за отсутствия g++library.
    Выполнить
    sudo apt-get -y update && sudo apt-get -y install gcc && sudo apt-get -y install g++
  3. При установке правильной версии tensorflow 1.x, использующей графический процессор, возникла проблема. Я полагаю, что правильный способ установить его - запустить pip install tensorflow-gpu==1.15
  4. Возникла проблема с агентом SSM, не имеющим правильных разрешений / политик. Всегда проверяйте, что агент SSM работает нормально и может подключаться к доступным экземплярам. Убедитесь, что вы выполнили Быструю настройку System Manager в Консоли AWS.
  5. Я столкнулся с проблемой, когда вывод происходил на CPU, а не на GPU. Оказалось, что это проблема с переменной окружения. LD_LIBRARY_PATH был установлен неправильно. В системном журнале была ошибка, указывающая на это, я заметил через некоторое время. Обратитесь к файлам gpt2-app- [model] .service для правильной настройки.
  6. Всегда смотрите / var / log / syslog, если сталкиваетесь с какой-либо проблемой. В большинстве случаев ошибка регистрируется там.
  7. Иногда экземпляр GPU не запускается из-за недостаточной емкости в зоне доступности. Вам нужно попробовать с другой АЗ.

Что дальше

Это приложение должно было помочь мне в работе с данными твиттера и изучении MLOps. Поэтому я определенно хочу перейти на конвейер Google AI Platform Pipeline для более полного развертывания рабочего процесса машинного обучения. Я также хочу иметь простой в использовании фреймворк для загрузки и хранения данных Twitter, поэтому я собираюсь изучить twint. Как только я это сделаю, мне будет легче работать над некоторыми другими идеями. Если у вас есть какие-либо собственные идеи / предложения относительно твиттера, дайте мне знать, оставив комментарий ниже.