Фаза 04 · урок 18

Зрение с открытым словарём — CLIP

Цель урока: Традиционные классификаторы имеют закрытый словарь: модель ImageNet на 1000 классов может предсказать только эти 1000 меток. Для каждой новой категории нужны размеченные данные и заново обученная голова.

Текущий релиз AlexBred.com: первые 100 уроков русскоязычной программы.

Курс
AI Engineering from Scratch
Фаза
Компьютерное зрение
Чтение
8 мин.
Проверено
Содержание урока
  1. Цели обучения
  2. Проблема
  3. Концепция
  4. Две башни
  5. Целевая функция
  6. SigLIP: лучшая функция потерь
  7. Классификация zero-shot
  8. Где модели в стиле CLIP используются в 2026 году
  9. Соберите это
  10. Шаг 1: крошечная двухбашенная модель
  11. Шаг 2: контрастивная функция потерь
  12. Шаг 3: классификатор zero-shot
  13. Шаг 4: быстрая проверка
  14. Используйте это
  15. Внедрите это
  16. Упражнения
  17. Ключевые термины
  18. Дополнительные материалы

Обучите кодировщик изображений и кодировщик текста вместе, чтобы соответствующие пары (изображение, подпись) попадали в одну точку общего пространства. В этом и заключается весь приём.

Тип: Соберите + используйте Языки: Python Предварительные требования: Фаза 4, урок 14 (ViT), фаза 4, урок 17 (Самообучение) Время: ~45 минут

Цели обучения

  • Объяснить двухбашенную архитектуру CLIP и цель контрастивного обучения
  • Использовать предобученный CLIP (или SigLIP) для классификации zero-shot без обучения под конкретную задачу
  • Реализовать классификацию zero-shot с нуля: кодировать промпты классов, вычислить косинусное сходство, взять argmax
  • Различать модели CLIP, SigLIP, OpenCLIP и LLaVA/LLaMA-vision — для чего каждая из них нужна в 2026 году

Проблема

Традиционные классификаторы имеют закрытый словарь: модель ImageNet на 1000 классов может предсказать только эти 1000 меток. Для каждой новой категории нужны размеченные данные и заново обученная голова.

CLIP (Radford et al., OpenAI, 2021) показал, что обучение на 400 млн пар (изображение, подпись), собранных из интернета, даёт модель, которая при инференсе может классифицировать в любой набор категорий, описанных только естественным языком. Новый класс задаётся предложением.

Эта способность — перенос zero-shot — объясняет, почему каждая современная система зрения начинается с чекпойнта семейства CLIP. Детекция (Grounding DINO, OWL-ViT), сегментация (CLIPSeg, SAM), поиск, модерация контента, VLM и генерация текста в изображение — все они опираются на совместные эмбеддинги в стиле CLIP.

Концепция

Две башни

Диаграмма к уроку «Зрение с открытым словарём — CLIP»

Оба кодировщика заканчиваются линейной проекцией в одну и ту же размерность эмбеддинга (512 для CLIP-B/32, 1024 для CLIP-L/14). Выполните L2-нормализацию и вычислите косинусное сходство.

Целевая функция

Для батча из N пар (изображение, подпись) постройте матрицу сходства NxN. Обучайте оба кодировщика так, чтобы на диагонали (соответствующие пары) сходство было высоким, а вне диагонали (несоответствующие пары) — низким.

sim_matrix = image_embeddings @ text_embeddings.T / tau

loss_i2t = cross_entropy(sim_matrix,       targets=arange(N))
loss_t2i = cross_entropy(sim_matrix.T,     targets=arange(N))
loss = (loss_i2t + loss_t2i) / 2

Функция симметрична, потому что должны работать и поиск изображения по тексту, и поиск текста по изображению. tau (температура) обычно обучается как скалярный параметр с инициализацией 0.07.

SigLIP: лучшая функция потерь

SigLIP (Zhai et al., 2023) заменил softmax попарным sigmoid:

loss = mean over pairs of log(1 + exp(-y_ij * sim_ij))
y_ij = +1 if matching, -1 otherwise

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

Классификация zero-shot

Для обученного CLIP:

  1. Для каждого класса составьте промпт: “a photo of a {class}”.
  2. Закодируйте все промпты классов текстовым кодировщиком -> T формы (C, d).
  3. Закодируйте тестовое изображение -> I формы (1, d).
  4. Сходство = I @ T.T формы (1, C).
  5. Argmax -> предсказанный класс.

Инженерия промптов важна. OpenAI опубликовала 80 шаблонов промптов для ImageNet (“a photo of a {}”, “a blurry photo of a {}”, “a sketch of a {}”, …). Усредните эмбеддинги всех шаблонов для каждого класса, чтобы получить дополнительно 1–3% точности top-1.

Где модели в стиле CLIP используются в 2026 году

  • Классификация zero-shot — прямое применение.
  • Поиск изображений — один раз закодируйте все изображения, а при инференсе встраивайте запрос.
  • Детекция, обусловленная текстом — Grounding DINO и OWL-ViT оборачивают текстовую башню CLIP вокруг детектора.
  • Сегментация, обусловленная текстом — CLIPSeg; SAM использует текстовые промпты через CLIP.
  • VLM — LLaVA, Qwen-VL и InternVL подключают кодировщик зрения семейства CLIP к LLM.
  • Генерация текста в изображение — Stable Diffusion и DALL-E 3 обусловливаются текстовыми эмбеддингами CLIP.

Когда есть общее пространство эмбеддингов, каждая задача «зрение + язык» превращается в вычисление расстояния.

Соберите это

Шаг 1: крошечная двухбашенная модель

Настоящий CLIP — это ViT + transformer. В этом уроке башни представляют собой небольшие MLP над заранее извлечёнными признаками, поэтому сигнал обучения виден на CPU.

import torch
import torch.nn as nn
import torch.nn.functional as F


class TwoTower(nn.Module):
    def __init__(self, img_in=128, txt_in=64, emb=64):
        super().__init__()
        self.image_proj = nn.Sequential(nn.Linear(img_in, 128), nn.ReLU(), nn.Linear(128, emb))
        self.text_proj = nn.Sequential(nn.Linear(txt_in, 128), nn.ReLU(), nn.Linear(128, emb))
        self.logit_scale = nn.Parameter(torch.ones([]) * 2.6592)  # ln(1/0.07)

    def forward(self, img_feats, txt_feats):
        i = F.normalize(self.image_proj(img_feats), dim=-1)
        t = F.normalize(self.text_proj(txt_feats), dim=-1)
        return i, t, self.logit_scale.exp()

Две проекции, выход общей размерности, обучаемая температура. Та же форма, что у настоящего API CLIP.

Шаг 2: контрастивная функция потерь

def clip_loss(image_emb, text_emb, logit_scale):
    N = image_emb.size(0)
    sim = logit_scale * image_emb @ text_emb.T
    targets = torch.arange(N, device=sim.device)
    l_i = F.cross_entropy(sim, targets)
    l_t = F.cross_entropy(sim.T, targets)
    return (l_i + l_t) / 2

Симметричная. Более высокий logit_scale = более острый softmax = более уверенные предсказания, но выше риск нестабильности.

Шаг 3: классификатор zero-shot

@torch.no_grad()
def zero_shot_classify(model, image_feats, class_text_feats, class_names):
    """
    image_feats:      (N, img_in)
    class_text_feats: (C, txt_in)   one averaged embedding per class
    """
    i = F.normalize(model.image_proj(image_feats), dim=-1)
    t = F.normalize(model.text_proj(class_text_feats), dim=-1)
    sim = i @ t.T
    pred = sim.argmax(dim=-1)
    return [class_names[p] for p in pred.tolist()]

Одна строка на шаг. Это точная процедура zero-shot, используемая с промышленным чекпойнтом CLIP.

Шаг 4: быстрая проверка

torch.manual_seed(0)
model = TwoTower()

img = torch.randn(8, 128)
txt = torch.randn(8, 64)
i, t, scale = model(img, txt)
loss = clip_loss(i, t, scale)
print(f"batch size: {i.size(0)}   loss: {loss.item():.3f}")

Для случайно инициализированной модели loss должна быть близка к log(N) = log(8) = 2.08 — симметричной цели кросс-энтропии, пока никакая структура ещё не выучена.

Используйте это

OpenCLIP — стандарт сообщества в 2026 году:

import open_clip
import torch
from PIL import Image

model, _, preprocess = open_clip.create_model_and_transforms("ViT-B-32", pretrained="laion2b_s34b_b79k")
tokenizer = open_clip.get_tokenizer("ViT-B-32")

image = preprocess(Image.open("dog.jpg")).unsqueeze(0)
text = tokenizer(["a photo of a dog", "a photo of a cat", "a photo of a car"])

with torch.no_grad():
    image_features = model.encode_image(image)
    text_features = model.encode_text(text)
    image_features = image_features / image_features.norm(dim=-1, keepdim=True)
    text_features = text_features / text_features.norm(dim=-1, keepdim=True)
    probs = (100.0 * image_features @ text_features.T).softmax(dim=-1)

print(probs)

SigLIP новее, лучше обучается при малых масштабах и предпочтителен для новой работы: google/siglip-base-patch16-224. Hugging Face предоставляет обе модели.

Внедрите это

Этот урок создаёт:

  • outputs/prompt-zero-shot-class-picker.md — промпт, который проектирует шаблоны классов для CLIP zero-shot по списку классов и предметной области.
  • outputs/skill-image-text-retriever.md — навык, который строит индекс эмбеддингов изображений с любым чекпойнтом CLIP, поддерживает запросы по тексту и по изображению.

Упражнения

  1. (Легко) Используйте предобученный OpenCLIP ViT-B/32 и выполните классификацию zero-shot на CIFAR-10 с набором из 80 шаблонов промптов. Сообщите точность top-1; она должна быть около 85–90%.
  2. (Средне) Сравните один шаблон (“a photo of a {}”) с эмбеддингами, усреднёнными по 80 шаблонам, на той же задаче CIFAR-10. Оцените разрыв и объясните, почему шаблоны помогают.
  3. (Сложно) Постройте индекс изображений для поиска zero-shot: вложите 1 000 изображений с CLIP, создайте индекс FAISS, выполните запрос с описанием на естественном языке. Сообщите recall@5 для 20 отложенных запросов, составленных вручную.

Ключевые термины

Термин Как говорят Что это в действительности означает
Две башни «Двойной кодировщик» Отдельные кодировщики изображения и текста, заканчивающиеся проекционной головой общей размерности
Zero-shot «Без обучения под конкретную задачу» Классификация в классы, описанные только текстом при инференсе; метки не используются
Temperature / logit_scale «tau» Обучаемый скаляр, масштабирующий матрицу сходства перед softmax
Шаблон промпта «A photo of a {}» Оболочка естественного языка вокруг названий классов; усреднение многих шаблонов повышает точность zero-shot
CLIP «Модель изображение+текст» Модель OpenAI 2021 года; основа словаря области в 2026 году
SigLIP «Sigmoid CLIP» Заменяет softmax на попарный sigmoid; лучше обучается на малых батчах
OpenCLIP «Открытое воспроизведение» Обученные сообществом варианты CLIP на LAION; промышленный стандарт для open-source конвейеров
VLM «Модель зрения и языка» Кодировщик семейства CLIP плюс LLM, обученные отвечать на вопросы об изображениях

Дополнительные материалы


Источник: Open-Vocabulary Vision — CLIP 04.17 — Самообучение для компьютерного зрения · Фаза 04 — Компьютерное зрение · 04.19 — OCR и понимание документов · Полный каталог