OpenAI’s Clip — это нейронная сеть, которая была обучена на огромном количестве пар изображений и текста и поэтому научилась связи между ними. Это означает, что он может встраивать текст и изображения в единое семантическое пространство, что позволяет нам использовать его для наиболее похожего изображения для данного текста или изображения.
Давайте попробуем создать собственный (небольшой) поиск картинок Google! Для этого нам необходимо:
- Преобразуйте изображения во вложения (= векторы) с помощью Clip
- Индексируйте векторы изображений с помощью Faiss
- Создайте поиск изображений, используя данные из предыдущих шагов.
Вложения изображений
Во-первых, нам нужно пропустить изображения через модель Clip, чтобы создать для них вложения. Это позволит нам найти изображение с наиболее похожим встраиванием (вектором) для заданного поискового запроса.
Я использую библиотеку sentence-transformers для загрузки предварительно обученной модели Clip. Библиотека предоставляет простой интерфейс для загрузки модели и взаимодействия с ней, поэтому преобразование изображений во встраивание выполняется довольно просто.
Кодирование одного изображения занимает ~20 мс с одним графическим процессором Nvidia V100, а 1 миллион изображений — ~90 минут. При большом количестве изображений полезно кодировать изображения большими пакетами, чтобы минимизировать накладные расходы на отправку данных в графический процессор.
Индекс для векторов изображений
Чтобы эффективно искать наиболее похожие изображения для данного текстового запроса, нам нужно их проиндексировать. Для этого доступно множество решений, в том числе некоторые решения PaaS, такие как Vertex AI Matching Engine, но я решил использовать Faiss. Faiss — это библиотека от Facebook для эффективного поиска сходства и кластеризации плотных векторов. Он предлагает множество различных функций, таких как:
- Базовый поиск сходства векторов без какой-либо кластеризации или сжатия
- Разделенный индекс с ячейками Вороного для приблизительного поиска (для ускорения поиска)
- Векторное сжатие с использованием квантования произведения (для уменьшения объема памяти)
Построение индекса
Я выбрал тип индекса IndexIVFFlat, который создает секционированный индекс для более быстрого поиска. Векторы группируются в кластеры (ячейки Вороного), и при поиске проверяются векторы из лучших кластеров. Это позволяет ускорить поиск, но может не всегда возвращать самые точные результаты. Вы можете балансировать между скоростью и точностью, выбирая количество кластеров, а также количество кластеров для посещения при поиске.
Плоская часть имени говорит о том, что векторы хранятся как есть, без какого-либо сжатия или квантования. Вы также можете выполнить квантование продукта, которое сжимает векторы в индексе. Это уменьшает объем памяти, но также аппроксимирует расчет сходства векторов и, следовательно, также снижает точность. У Faiss есть действительно хорошая документация на их странице Github о различных индексах и методах сжатия: https://github.com/facebookresearch/faiss/wiki/Faiss-indexes
Функция index_factory позволяет легко создавать эти составные индексы, поскольку нам нужен индекс для поиска лучшего кластера, а затем еще один индекс для векторов в кластере.
Обучение просто находит наиболее оптимальные центроиды кластера, поэтому вам не обязательно обучать его со всеми индексами. Я также добавляю векторы в индекс с идентификаторами, чтобы было проще искать фактические файлы изображений. Идентификатор — это просто уникальное случайное число, которое также будет использоваться в качестве имени файла изображения в GCS.
Поиск изображений
Поиск наиболее похожих изображений для данного текста — это просто векторный поиск сходства:
- Преобразуйте текст в вектор запроса
- Найдите наиболее похожие векторы из индекса для вектора запроса
- Поиск файлов изображений из GCS с использованием идентификатора вектора (изображения)
Многоязычная версия модели OpenAI CLIP-ViT-B32 (clip-ViT-B-32-multilingual-v1) из библиотеки преобразователей предложений может использоваться для вектор. Это позволяет нам отображать текст на любом языке в одно семантическое пространство с изображениями. т.е. текст «красная машина» или «carro rojo» получит тот же вектор, что и изображение красной машины.
Вы можете убедиться в силе Clip, изменив «мужчины» на «женщины» в предыдущем поисковом запросе. Клип может отличать женщин от мужчин (в традиционном двуполом мире), поэтому вместо этого вы увидите фотографии женщин, играющих в футбол. Конечно, Clip на самом деле не понимает полов, но только что узнал, что эти типы изображений появляются вместе со словом «женщины».
Как было сказано, поскольку это просто векторный поиск сходства, вы можете использовать любой вектор для поиска, включая вектор, созданный из изображения:
Вышеприведенный код ищет наиболее похожие на фото гамбургера изображения, которые (сюрприз, сюрприз) тоже о гамбургерах.
Хороший! Как видите, вы можете довольно легко создать свой собственный поиск изображений и начать конкурировать с Google! Что ж, вам может понадобиться несколько дополнительных изображений в вашем индексе и распределенный индекс.
Что касается Clip и всех языковых моделей, хорошо помнить, что они имеют различные предубеждения. Или, скорее, они узнали их из содержания, на котором они были обучены. Например, они могут ассоциировать врачей с мужчинами, а домработниц с женщинами. Или, если определенные группы людей совершают больше преступлений, чем другие, вы можете получить изображения этих групп в качестве результатов при поиске фотографий преступлений. Вот одно связанное исследование предубеждений в клипе OpenAI: https://venturebeat.com/2021/08/10/audit-finds-gender-and-age-bias-in-openais-clip-model/