Вопросы о CLIP-моделях встречаются почти на каждом техническом собеседовании.
Неважно, занимаетесь ли вы видеоаналитикой, создаёте генеративные модели или работаете над поиском по изображениям — CLIP и его потомки (BLIP , SigLIP ) стали стандартом де-факто в задачах связи визуальных и текстовых данных. Почему? Потому что они позволяют решать задачи, которые ранее требовали значительных усилий: от автоматической разметки данных до генерации изображений по текстовым запросам. А значит, на собеседовании вас спросят, как устроены эти модели, зачем они нужны и в чём их преимущества перед классическими подходами.

Cхема CLIP фреймворка

Зачем знать про CLIP-модели:

  1. Автоматическая разметка (zero-shot) без участия людей.

  2. Поиск похожих изображений/дубликатов .

  3. Связь текста и изображений в генеративных задачах

    Связь CLIP моделей текста и картинок

Я - Рома Филонов. Работал в Яндексе, Сбере и компаниях по-меньше. Senior Computer vision разработчик, в моем канале найдешь больше о подготовке к собеседованиям и о нейросетях. ПОДПИШИСЬ!

Общие сведения

CLIP (Contrastive Language–Image Pretraining) — модель, которая обучается сопоставлять изображения и текстовые описания без явной разметки. Например, если у вас есть изображение кошки и текст «кошка», модель научится связывать их в общем векторном пространстве. Это открывает возможности zero-shot обучения — когда модель может классифицировать объекты, отсутствующие в обучающей выборке.

Как это работает?

  1. Два энкодера :

    • Для текста (может быть что угодно, например, линейные слои).

    • Для изображений (CNN или Vision Transformer).

  2. Общее векторное пространство : модель учится так, чтобы векторы изображения и соответствующего текста были близки, а несвязанные пары — далеко.

  3. Zero-shot inference : вместо обучения на конкретных классах вы передаёте модели текстовые описания («кошка», «собака», «машина»), и она выбирает наиболее подходящее.

Пример : загрузив изображение ежика, CLIP «понимает», что это «животное с иголками», даже если таких примеров не было в обучающих данных.

Схема обучения двух энкодеров в CLIP подходе

Обучение модели

Обучение CLIP основано на contrastive-подходе — модель сравнивает элементы обучающей выборки между собой. В отличие от классического supervised-обучения (например, классификатора «кошка/собака» с метками и Cross-entropy loss), здесь всё обучение строится на попарных сравнениях изображений и текстовых описаний.

Обучающая выборка

Каждый элемент — это пара (изображение, текстовое описание). Формируется батч таких пар, и все они сравниваются между собой.

Архитектура

  1. Image encoder : ResNet или Vision Transformer.

  2. Text encoder : CBOW или Text Transformer.

Процесс :

  1. Прогоняем изображения через image encoder и тексты через text encoder.

  2. Получаем N векторов для изображений и N векторов для текстов.

  3. Сравниваем их по косинусной мере или MSE.

  4. Получаем матрицу сравнений 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

Алгоритм :

  1. Для каждой i-й пары вычисляется Softmax по косинусному сходству с другими текстами.

  2. Считается Cross-entropy для строк (изображения) и столбцов (тексты) матрицы.

  3. Итоговая потеря — среднее двух значений.

Проблема размера батча

Для обучения CLIP требуется очень большой батч.
В статье использовался размер 1712 (а в дальнейших экспериментах — ещё больше).

Это проблема, так как такой батч не помещается в одну GPU. Решение — распределённое обучение с разделением данных между GPU.

Пруф из статьи о размере батча

SigLIP

SigLIP: улучшение CLIP (Sigmoid Loss for Image-Text Contrastive Learning)

SigLIP — это улучшенная версия CLIP, разработанная командой Google Research для решения ключевых проблем масштабируемости и вычислительной эффективности при обучении мультимодальных моделей. Основная цель SigLIP — упростить распределённое обучение на очень больших батчах, сохранив при этом качество эмбеддингов.

Основная идея SigLIP

В отличие от CLIP, который использует softmax для нормализации косинусного сходства между парами изображений и текстов, SigLIP заменяет softmax на сигмоиду . Это позволяет:

  1. Убрать необходимость глобального нормирования (softmax) при вычислении потерь.

  2. Распределить вычисления между GPU без синхронизации на этапе подсчёта потерь.

Ключевое отличие :

  • CLIP : Использует softmax для нормализации косинусного сходства. Это требует, чтобы все пары (изображения + тексты) находились на одном устройстве для вычисления вероятностей.

  • SigLIP : Использует сигмоиду для каждой пары независимо, что позволяет обрабатывать данные на разных устройствах параллельно.

Благодаря этому мы можем эффективно скейлить наши батчи до абсурдных размеров в 1млн пар!!! (Как говорится в статье)

Также авторы придумали как эффективно провести сравнение всех векторов изображений и текстов.

Мы поочередно раскидываем текста и изображения по разным видеокартам добиваясь сравнения каждого текста с каждым изображением. 

Авторы занялись подбором оптимального размера батча, проверяли от на размерах от 512 до 1млн. По итогам лучшие результаты были на 16к и 32к. Что нам обычным смертным не посильно воспроизвести на паре видеокарт. 

Изображение из статьи - https://arxiv.org/pdf/2303.15343

Пример запуска 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)

Вот такая у нас картинка с котами

2 кота

И вот такой результат мы получим

[{'score': 0.1979, 'label': '2 cats'}, {'score': 0.0, 'label': 'a remote'}, {'score': 0.0, 'label': 'a plane'}]

Пиши в комментарии о чем хочешь еще подробнее узнать.

Также читай


Полный гайд про то как ПРАВИЛЬНО ДООБУЧАТЬ модели в 2025 году

Пошаговая инструкция как АРЕНДОВАТЬ GPU

Подписывайся на мои ресурсы, чтобы узнать больше и расти в сфере ML