Вопросы о CLIP-моделях встречаются почти на каждом техническом собеседовании.
Неважно, занимаетесь ли вы видеоаналитикой, создаёте генеративные модели или работаете над поиском по изображениям — CLIP и его потомки (BLIP , SigLIP ) стали стандартом де-факто в задачах связи визуальных и текстовых данных. Почему? Потому что они позволяют решать задачи, которые ранее требовали значительных усилий: от автоматической разметки данных до генерации изображений по текстовым запросам. А значит, на собеседовании вас спросят, как устроены эти модели, зачем они нужны и в чём их преимущества перед классическими подходами.
Зачем знать про CLIP-модели:
-
Автоматическая разметка (zero-shot) без участия людей.
-
Поиск похожих изображений/дубликатов .
-
Связь текста и изображений в генеративных задачах
Связь CLIP моделей текста и картинок
Я — Рома Филонов. Работал в Яндексе, Сбере и компаниях по-меньше. Senior Computer vision разработчик, в моем канале найдешь больше о подготовке к собеседованиям и о нейросетях. ПОДПИШИСЬ!
Общие сведения
CLIP (Contrastive Language–Image Pretraining) — модель, которая обучается сопоставлять изображения и текстовые описания без явной разметки. Например, если у вас есть изображение кошки и текст «кошка», модель научится связывать их в общем векторном пространстве. Это открывает возможности zero-shot обучения — когда модель может классифицировать объекты, отсутствующие в обучающей выборке.
Как это работает?
-
Два энкодера :
-
Для текста (может быть что угодно, например, линейные слои).
-
Для изображений (CNN или Vision Transformer).
-
-
Общее векторное пространство : модель учится так, чтобы векторы изображения и соответствующего текста были близки, а несвязанные пары — далеко.
-
Zero-shot inference : вместо обучения на конкретных классах вы передаёте модели текстовые описания («кошка», «собака», «машина»), и она выбирает наиболее подходящее.
Пример : загрузив изображение ежика, CLIP «понимает», что это «животное с иголками», даже если таких примеров не было в обучающих данных.
Обучение модели
Обучение CLIP основано на contrastive-подходе — модель сравнивает элементы обучающей выборки между собой. В отличие от классического supervised-обучения (например, классификатора «кошка/собака» с метками и Cross-entropy loss), здесь всё обучение строится на попарных сравнениях изображений и текстовых описаний.
Обучающая выборка
Каждый элемент — это пара (изображение, текстовое описание). Формируется батч таких пар, и все они сравниваются между собой.
Архитектура
-
Image encoder : ResNet или Vision Transformer.
-
Text encoder : CBOW или Text Transformer.
Процесс :
-
Прогоняем изображения через image encoder и тексты через text encoder.
-
Получаем N векторов для изображений и N векторов для текстов.
-
Сравниваем их по косинусной мере или MSE.
-
Получаем матрицу сравнений NxN, по которой вычисляется функция потерь.
Ошибочное представление
Многие думают, что в contrastive-обучении используется margin loss. Однако в CLIP обучение происходит через Cross-entropy loss .
Детали реализации
# Пример кода I_f = image_encoder(I) # [n, d_i] T_f = text_encoder(T) # [n, d_t] # Проекция в общее пространство I_e = l2_normalize(np.dot(I_f, W_i), axis=1) T_e = l2_normalize(np.dot(T_f, W_t), axis=1) # Матрица сходства logits = np.dot(I_e, T_e.T) * np.exp(t) # Вычисление потерь labels = np.arange(n) loss_i = cross_entropy_loss(logits, labels, axis=0) loss_t = cross_entropy_loss(logits, labels, axis=1) loss = (loss_i + loss_t) / 2
Алгоритм :
-
Для каждой i-й пары вычисляется Softmax по косинусному сходству с другими текстами.
-
Считается Cross-entropy для строк (изображения) и столбцов (тексты) матрицы.
-
Итоговая потеря — среднее двух значений.
Проблема размера батча
Для обучения CLIP требуется очень большой батч.
В статье использовался размер 1712 (а в дальнейших экспериментах — ещё больше).
Это проблема, так как такой батч не помещается в одну GPU. Решение — распределённое обучение с разделением данных между GPU.
SigLIP
SigLIP: улучшение CLIP (Sigmoid Loss for Image-Text Contrastive Learning)
SigLIP — это улучшенная версия CLIP, разработанная командой Google Research для решения ключевых проблем масштабируемости и вычислительной эффективности при обучении мультимодальных моделей. Основная цель SigLIP — упростить распределённое обучение на очень больших батчах, сохранив при этом качество эмбеддингов.
Основная идея SigLIP
В отличие от CLIP, который использует softmax для нормализации косинусного сходства между парами изображений и текстов, SigLIP заменяет softmax на сигмоиду . Это позволяет:
-
Убрать необходимость глобального нормирования (softmax) при вычислении потерь.
-
Распределить вычисления между GPU без синхронизации на этапе подсчёта потерь.
Ключевое отличие :
-
CLIP : Использует softmax для нормализации косинусного сходства. Это требует, чтобы все пары (изображения + тексты) находились на одном устройстве для вычисления вероятностей.
-
SigLIP : Использует сигмоиду для каждой пары независимо, что позволяет обрабатывать данные на разных устройствах параллельно.
Благодаря этому мы можем эффективно скейлить наши батчи до абсурдных размеров в 1млн пар!!! (Как говорится в статье)
Также авторы придумали как эффективно провести сравнение всех векторов изображений и текстов.
Мы поочередно раскидываем текста и изображения по разным видеокартам добиваясь сравнения каждого текста с каждым изображением.
Авторы занялись подбором оптимального размера батча, проверяли от на размерах от 512 до 1млн. По итогам лучшие результаты были на 16к и 32к. Что нам обычным смертным не посильно воспроизвести на паре видеокарт.
Пример запуска SigLIP
from transformers import pipeline from PIL import Image import requests # Загружаем пайплайн image_classifier = pipeline(task="zero-shot-image-classification", model="google/siglip-base-patch16-224") # Загружаем изображение url = 'http://images.cocodataset.org/val2017/000000039769.jpg' image = Image.open(requests.get(url, stream=True).raw) # Делаем Zero-shot классификацию candidate_labels = ["2 cats", "a plane", "a remote"] outputs = image_classifier(image, candidate_labels=candidate_labels) outputs = [{"score": round(output["score"], 4), "label": output["label"] } for output in outputs] print(outputs)
Вот такая у нас картинка с котами
И вот такой результат мы получим
[{'score': 0.1979, 'label': '2 cats'}, {'score': 0.0, 'label': 'a remote'}, {'score': 0.0, 'label': 'a plane'}]
Пиши в комментарии о чем хочешь еще подробнее узнать.
Также читай
Полный гайд про то как ПРАВИЛЬНО ДООБУЧАТЬ модели в 2025 году
Пошаговая инструкция как АРЕНДОВАТЬ GPU
Подписывайся на мои ресурсы, чтобы узнать больше и расти в сфере ML
ссылка на оригинал статьи https://habr.com/ru/articles/908168/
Добавить комментарий