CLIP или SigLIP. База по Computer vision собеседованиям. Middle/Senior
Вопросы о 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