Как научить машину описывать изображение?

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

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

  • Основное объяснение сверточной нейронной сети
  • Извлечение описания изображения с использованием модели глубокого обучения
  • Создание службы обратного поиска изображений с использованием извлеченной функции

Сверточная нейронная сеть: взгляд машины

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

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

Для этого каждый слой будет пытаться применить некоторые фильтры ко входу и вывести представление «нового изображения». Это делается с помощью сверточных фильтров, как показано на рис. 1. Мы применяем фильтр 3x3 ко входу (синее изображение) и получаем сжатый результат (зеленое изображение). Окно 3x3 входного изображения будет умножено на веса фильтра, и на выходе будет получена одна выходная ячейка.

Применяя эту стратегию, мы сможем зафиксировать пространственную корреляцию между соседними пикселями входного изображения. Передача результата на следующие уровни позволит сети захватывать еще более сложные объекты. Это можно проиллюстрировать на рис. 2. Первые слои могут извлекать низкоуровневые функции, такие как линии и края. Затем средние слои смогут извлекать кривые. Последние слои могут различать более высокоуровневые элементы, такие как форма шины от автомобиля или крыло птицы.

Затем высокоуровневые объекты сглаживаются в 1D-вектор. Вектор подается в полностью подключенную сеть, чтобы сделать прогноз класса. Таким образом, наша машина сможет различать изображения кошек и собак!

Извлечение функции изображения с помощью глубокой нейронной сети

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

Одной из широко используемых моделей глубокого CNN является VGG, разработанная некоторыми исследователями из группы визуальной геометрии Оксфордского университета. Существует несколько версий сети VGG, например VGG16, который относится к 16-уровневой версии VGG, и VGG19, относящийся к его 19-уровневой версии.

На изображении выше сеть принимает входное изображение размером 224x224x3. Часть от первого сверточного слоя до последнего объединенного игрока (7x7x512) является частью извлечения признаков. Затем оставшиеся слои являются классификационной частью. Итак, если мы хотим получить особенность изображения, нам нужен только результат части извлечения признаков.

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

Скрипт загрузит предварительно обученную модель VGG16, а затем усечет архитектуру, чтобы мы включили только часть извлечения свойств, указав include_top=False в аргументе. Затем мы загружаем каждое изображение в базу данных и предварительно обрабатываем его для получения желаемого входного изображения 224x224x3. После этого мы загружаем изображение в сеть VGG16 и извлекаем его функцию. Затем окончательная матрица признаков (размером 7x7x512) выравнивается, чтобы получился 1D-вектор.

Создание службы обратного поиска изображений

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

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

Мы знаем, что наш вектор очень длинный (в нем 25 088 элементов!). Однако для простоты предположим, что в нашем векторном представлении всего 2 элемента. Итак, векторы можно построить, как на рис.3.

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

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

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

В scikit-learn мы можем использовать NearestNeighbors для реализации обратного поиска изображений. Нам нужно указать metric=cosine в аргументе класса, чтобы использовать косинусное расстояние в качестве нашей метрики.

Результат следующий.