Я записался на наностепень компьютерного зрения udacity, и один из проектов — использовать pytorch для создания модели подписей к изображениям с помощью CNN и seq2seq LSTM.

Набор данных

Используется набор данных COCO. Я следую за udacity и использую данные за 2014 год, вы можете загрузить и использовать более обновленный набор данных COCO и получить лучший результат.

Инициализировать COCO API

Мы можем следить за официальным репозиторием github, чтобы узнать, как использовать COCO API. Введите путь к файлу аннотаций, после чего мы сможем визуализировать изображение из набора данных.

Предварительно обработать изображение:

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

Предварительно обработайте подписи:

Первоначальные подписи были в текстовой форме, но наша модель не может напрямую читать английский язык, мы должны сначала преобразовать текст в целое число. Мы можем использовать NLTK (или другой метод NLP) для токенизации и создания словаря сопоставления, чтобы присвоить каждому уникальному текстовому токену целое число. Мы также можем применить некоторый порог, чтобы отфильтровать очень редкие или распространенные слова, подсчитав их появление в корпусе.

Например, необработанное текстовое предложение «Я мальчик» будет преобразовано в [‹начало›, 'я', 'ам', 'а', 'мальчик', ‹конец›] и в конечном итоге станет [0, 3, 98, 754, 3, 1].

SubsetRandomSampler

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

Или мы можем использовать SubsetRandomSampler в pytorch для случайной выборки элементов из заданного списка индексов. Сначала мы генерируем случайное число ≤max длина подписей, например 13. Затем мы используем np.where, чтобы получить все индексы подписей, имеющих длину = 13.

Создайте кодировщик

Для части извлечения изображений я не создавал ее с нуля, потому что это не очень строгая задача классификации изображений. Вместо этого я применяю предварительно обученный resnet50, потому что это сэкономит мне много времени. Не забудьте удалить последний слой FC, поскольку мы не занимаемся классификацией изображений, нам просто нужно извлечь функцию и соединить вектор функции с LSTM в декодере. Не забудьте заморозить параметр resnet50, иначе вы уничтожите тренировочный вес.

Создайте декодер

Мы уже преобразовали текстовое предложение в целочисленный токен, теперь мы добавляем слой встраивания слов, чтобы увеличить способность представления нашей модели. Не забудьте объединить вектор признаков (изображение) и нашу матрицу встраивания (заголовки), чтобы передать их в LSTM.

Гиперпараметр

Я всегда использую оптимизатор Adam, мой первый выбор.

Размер пакета = 512, это максимум, который может себе позволить мой GPU.

Скорость обучения от 0,01 до 0,001, зависит от количества эпох. Я не применил запланированную скорость обучения с затуханием/отжигом, потому что предпочитаю точную настройку вручную. Когда я вижу, что убыток сглаживается, я понижаю lr.

Результат

Фактическая эпоха, которую я тренировал, была старше 15+, но я не записывал все данные о потерях. Поскольку этот проект предназначен только для моего собственного интереса, я не планирую повторно запускать его только для того, чтобы получить все отслеживание. (Обратите внимание, что рекомендуется хранить все записи об эпохе, lr и данных о потерях… и т. д.)

Не забудьте применить те же шаги предварительной обработки изображения к набору тестовых изображений. Тестируемое изображение будет проходить те же этапы предварительной обработки и передаваться в модель для вывода токена, затем мы сопоставляем целочисленный токен со словарем word2idx, чтобы получить текстовый токен. Этот токен также становится входом нашей модели для прогнозирования следующего токена. Он зацикливается до тех пор, пока наша модель не прочитает токен ‹stop›.

Полный код

Вот полный код, наслаждайтесь