Фаза 04 · урок 12

Понимание видео — временное моделирование

Цель урока: 30-секундное видео при 30 fps — это 900 изображений. Наивно классификация видео — это классификация изображений, запущенная 900 раз с последующей агрегацией. Такой подход работает, когда действие видно почти в каждом кадре (спорт,…

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

Курс
AI Engineering
Фаза
Компьютерное зрение
Чтение
11 мин.
Проверено
Содержание урока
  1. Цели обучения
  2. Проблема
  3. Концепция
  4. Три семейства архитектур
  5. 2D + pool
  6. 3D-свёртки
  7. Пространственно-временные трансформеры
  8. Выборка кадров
  9. Оценка
  10. Наборы данных, которые вы встретите
  11. Соберите
  12. Шаг 1: Сэмплер кадров
  13. Шаг 2: Базовое решение 2D+pool
  14. Шаг 3: Раздутая 3D-свёртка в стиле I3D
  15. Шаг 4: Факторизованная свёртка (2+1)D
  16. Используйте
  17. Поставьте
  18. Упражнения
  19. Ключевые термины
  20. Дополнительные материалы

Видео — это последовательность изображений плюс физика, которая их связывает. Каждая модель видео либо рассматривает время как дополнительную ось (3D-свёртка), либо как последовательность для внимания (transformer), либо извлекает признаки один раз и агрегирует их (2D+pool).

Тип: Изучите + соберите Языки: Python Предварительные требования: Фаза 4, урок 03 (CNN), фаза 4, урок 04 (Классификация изображений) Время: ~45 минут

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

  • Различать три основных подхода к моделированию видео (2D+pool, 3D-свёртки, пространственно-временные трансформеры) и предсказывать их компромиссы между стоимостью и точностью
  • Реализовать выборку кадров, временной pooling и базовый классификатор 2D+pool в PyTorch
  • Объяснить, почему «раздутые» (inflated) 3D-ядра I3D хорошо переносят веса ImageNet и чем факторизованная свёртка (2+1)D отличается от них
  • Ориентироваться в стандартных наборах данных и метриках распознавания действий: Kinetics-400/600, UCF101, Something-Something V2; точность top-1 на уровне клипа и видео

Проблема

30-секундное видео при 30 fps — это 900 изображений. Наивно классификация видео — это классификация изображений, запущенная 900 раз с последующей агрегацией. Такой подход работает, когда действие видно почти в каждом кадре (спорт, готовка, упражнения), и плохо работает, когда действие определяется самим движением: «толкнуть что-то слева направо» в каждом отдельном кадре выглядит как два неподвижных объекта.

Главный вопрос для каждой видеоархитектуры: когда и как моделируется временная структура? Ответ определяет всё остальное — стоимость вычислений, стратегию предобучения, возможность повторно использовать веса ImageNet и наборы данных, на которых обучается модель.

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

Концепция

Три семейства архитектур

Диаграмма к уроку «Понимание видео — временное моделирование»

2D + pool

Возьмите 2D CNN (ResNet, EfficientNet, ViT). Запустите её независимо на каждом выбранном кадре. Усредните (или примените max-pool либо attention-pool к) встраиваниям кадров. Передайте агрегированный вектор классификатору.

Преимущества:

  • Предобучение ImageNet переносится напрямую.
  • Самая простая реализация.
  • Дёшево: T кадров * стоимость инференса одного изображения.

Недостатки:

  • Не может моделировать движение. Действие = агрегация внешних признаков.
  • Временной pooling инвариантен к порядку; «открыть дверь» и «закрыть дверь» выглядят одинаково.

Когда использовать: задачи, где важен внешний вид, transfer learning на небольших наборах видео, первоначальные базовые решения.

3D-свёртки

Замените 2D-ядра (H, W) на 3D-ядра (T, H, W). Сеть выполняет свёртку и по пространству, и по времени. Ранние представители семейства: C3D, I3D, SlowFast.

Приём I3D: возьмите предобученную 2D-модель ImageNet и «раздуйте» каждое 2D-ядро, копируя его вдоль новой временной оси. Свёртка 2D 3x3 превращается в свёртку 3D 3x3x3. Так 3D-модель получает сильные предобученные веса вместо обучения с нуля.

Преимущества:

  • Непосредственно моделирует движение.
  • Раздувание I3D даёт бесплатное transfer learning.

Недостатки:

  • В T/8 раз больше FLOPs, чем у 2D-аналога (для временного ядра 3, применённого трижды в стеке).
  • Временные ядра малы; для дальнего движения нужна пирамида или двухпоточный подход.

Когда использовать: распознавание действий, где движение — это сигнал (Something-Something V2, Kinetics с классами, сильно зависящими от движения).

Пространственно-временные трансформеры

Токенизируйте видео в сетку пространственно-временных патчей и выполняйте внимание по всем им. TimeSformer, ViViT, Video Swin, VideoMAE.

Важные паттерны внимания:

  • Совместное (joint) — одно большое внимание по (t, h, w). Квадратичное по T*H*W; дорого.
  • Разделённое (divided) — два внимания на блок: одно по времени, другое по пространству. Почти линейное масштабирование.
  • Факторизованное (factorised) — внимание по времени чередуется с вниманием по пространству между блоками.

Преимущества:

  • SOTA-точность на каждом крупном бенчмарке.
  • Переносится из трансформеров изображений (ViT) через раздувание патчей.
  • Поддерживает видео с длинным контекстом через разреженное внимание.

Недостатки:

  • Требователен к вычислениям.
  • Требует тщательного выбора паттерна внимания, иначе время выполнения резко растёт.

Когда использовать: большие наборы данных, высокоточное понимание видео, мультимодальные задачи видео+текст.

Выборка кадров

10-секундный клип при 30 fps — это 300 кадров; подавать все 300 в любую модель расточительно. Стандартные стратегии:

  • Равномерная выборка (uniform sampling) — выбрать T кадров равномерно по всему клипу. Значение по умолчанию для 2D+pool.
  • Плотная выборка (dense sampling) — случайное непрерывное окно из T кадров. Обычна для 3D-свёрток, поскольку движение требует соседних кадров.
  • Несколько клипов (multi-clip) — выбрать несколько окон из T кадров из одного видео, классифицировать каждое и усреднить предсказания во время тестирования.

T обычно равно 8, 16, 32 или 64. Большее T означает больше временного сигнала за большую цену вычислений.

Оценка

Два уровня:

  • Точность на уровне клипа — модель видит один клип из T кадров и возвращает top-k.
  • Точность на уровне видео — усредняйте предсказания на уровне клипа по нескольким клипам каждого видео; она выше и стабильнее.

Всегда сообщайте обе. Модель с 78% для клипа / 82% для видео сильно полагается на усреднение во время теста; модель с 80% / 81% более устойчива на каждом клипе.

Наборы данных, которые вы встретите

  • Kinetics-400 / 600 / 700 — универсальный набор данных действий. 400 тыс. клипов; URL YouTube (многие уже недоступны).
  • Something-Something V2 — действия, определяемые движением («переместить X слева направо»). Нельзя решить с помощью 2D+pool.
  • UCF-101, HMDB-51 — старые, небольшие, но всё ещё упоминаемые наборы.
  • AVA — локализация действий в пространстве и времени; сложнее классификации.

Соберите

Шаг 1: Сэмплер кадров

Равномерный и плотный сэмплеры, работающие со списком кадров (или тензором видео).

import numpy as np

def sample_uniform(num_frames_total, T):
    if num_frames_total <= T:
        return list(range(num_frames_total)) + [num_frames_total - 1] * (T - num_frames_total)
    step = num_frames_total / T
    return [int(i * step) for i in range(T)]


def sample_dense(num_frames_total, T, rng=None):
    rng = rng or np.random.default_rng()
    if num_frames_total <= T:
        return list(range(num_frames_total)) + [num_frames_total - 1] * (T - num_frames_total)
    start = int(rng.integers(0, num_frames_total - T + 1))
    return list(range(start, start + T))

Оба возвращают T индексов, которые используются для среза тензора видео.

Шаг 2: Базовое решение 2D+pool

Запустите 2D ResNet-18 на каждом кадре, усредните признаки и классифицируйте.

import torch
import torch.nn as nn
from torchvision.models import resnet18, ResNet18_Weights

class FramePool(nn.Module):
    def __init__(self, num_classes=400, pretrained=True):
        super().__init__()
        weights = ResNet18_Weights.IMAGENET1K_V1 if pretrained else None
        backbone = resnet18(weights=weights)
        self.features = nn.Sequential(*(list(backbone.children())[:-1]))  # global avg pool kept
        self.head = nn.Linear(512, num_classes)

    def forward(self, x):
        # x: (N, T, 3, H, W)
        N, T = x.shape[:2]
        x = x.view(N * T, *x.shape[2:])
        feats = self.features(x).view(N, T, -1)
        pooled = feats.mean(dim=1)
        return self.head(pooled)

model = FramePool(num_classes=10)
x = torch.randn(2, 8, 3, 224, 224)
print(f"output: {model(x).shape}")
print(f"params: {sum(p.numel() for p in model.parameters()):,}")

Одиннадцать миллионов параметров, предобучение ImageNet, работа по кадрам, усреднение, классификация. На задачах, где важен внешний вид, это базовое решение часто отстаёт от настоящих 3D-моделей лишь на 5–10 пунктов — а иногда лучше, потому что повторно использует более сильный backbone ImageNet.

Шаг 3: Раздутая 3D-свёртка в стиле I3D

Превратите одну 2D-свёртку в 3D-свёртку, повторив веса вдоль новой временной оси.

def inflate_2d_to_3d(conv2d, time_kernel=3):
    out_c, in_c, kh, kw = conv2d.weight.shape
    weight_3d = conv2d.weight.data.unsqueeze(2)  # (out, in, 1, kh, kw)
    weight_3d = weight_3d.repeat(1, 1, time_kernel, 1, 1) / time_kernel
    conv3d = nn.Conv3d(in_c, out_c, kernel_size=(time_kernel, kh, kw),
                        padding=(time_kernel // 2, conv2d.padding[0], conv2d.padding[1]),
                        stride=(1, conv2d.stride[0], conv2d.stride[1]),
                        bias=False)
    conv3d.weight.data = weight_3d
    return conv3d

conv2d = nn.Conv2d(3, 64, kernel_size=3, padding=1, bias=False)
conv3d = inflate_2d_to_3d(conv2d, time_kernel=3)
print(f"2D weight shape:  {tuple(conv2d.weight.shape)}")
print(f"3D weight shape:  {tuple(conv3d.weight.shape)}")
x = torch.randn(1, 3, 8, 56, 56)
print(f"3D output shape:  {tuple(conv3d(x).shape)}")

Деление на time_kernel сохраняет величины активаций примерно постоянными — это важно, чтобы при первом проходе не нарушить статистики batch norm.

Шаг 4: Факторизованная свёртка (2+1)D

Разделите 3D-свёртку на 2D-свёртку (пространственную) и 1D-свёртку (временную). То же поле восприятия, меньше параметров, на некоторых бенчмарках — лучше точность.

class Conv2Plus1D(nn.Module):
    def __init__(self, in_c, out_c, kernel_size=3):
        super().__init__()
        mid_c = (in_c * out_c * kernel_size * kernel_size * kernel_size) \
                // (in_c * kernel_size * kernel_size + out_c * kernel_size)
        self.spatial = nn.Conv3d(in_c, mid_c, kernel_size=(1, kernel_size, kernel_size),
                                 padding=(0, kernel_size // 2, kernel_size // 2), bias=False)
        self.bn = nn.BatchNorm3d(mid_c)
        self.act = nn.ReLU(inplace=True)
        self.temporal = nn.Conv3d(mid_c, out_c, kernel_size=(kernel_size, 1, 1),
                                  padding=(kernel_size // 2, 0, 0), bias=False)

    def forward(self, x):
        return self.temporal(self.act(self.bn(self.spatial(x))))

c = Conv2Plus1D(3, 64)
x = torch.randn(1, 3, 8, 56, 56)
print(f"(2+1)D output: {tuple(c(x).shape)}")

Полная сеть R(2+1)D устроена так же, как ResNet-18, только каждая свёртка 3x3 заменена на Conv2Plus1D.

Используйте

Две библиотеки покрывают рабочие задачи с видео:

  • torchvision.models.video — R(2+1)D, MViT, Swin3D с предобученными весами Kinetics. Тот же API, что у моделей изображений.
  • pytorchvideo (Meta) — зоопарк моделей, загрузчики данных для Kinetics / SSv2 / AVA, стандартные преобразования.

Для video-language-моделей (создание подписей к видео, video QA) используйте transformers (VideoMAE, VideoLLaMA, InternVideo).

Поставьте

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

  • outputs/prompt-video-architecture-picker.md — промпт, который выбирает 2D+pool / I3D / (2+1)D / transformer по соотношению внешнего вида и движения, размеру набора данных и бюджету вычислений.
  • outputs/skill-frame-sampler-auditor.md — навык, который проверяет сэмплер видеоконвейера и отмечает распространённые ошибки: off-by-one в индексе, неравномерную выборку при num_frames < T, отсутствие кропа с сохранением соотношения сторон и т. д.

Упражнения

  1. (Легко) Вычислите FLOPs (приблизительно) для FramePool с T=8 и для 3D ResNet в стиле I3D с T=8. Объясните, почему 2D+pool в 3–5 раз дешевле.
  2. (Средне) Создайте синтетический набор видео: случайные шарики движутся в случайных направлениях и размечаются направлением движения («слева направо», «справа налево», «по диагонали вверх»). Обучите на нём FramePool. Покажите, что она достигает точности, близкой к случайной, доказывая недостаточность одного лишь внешнего вида для задач движения.
  3. (Сложно) Постройте R(2+1)D-18, заменив каждую Conv2d в ResNet-18 на Conv2Plus1D. Раздуйте веса первой свёртки из предобученной на ImageNet ResNet-18. Обучите на наборе движения из упражнения 2 и превзойдите FramePool.

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

ТерминКак обычно говорятЧто это на самом деле означает
2D + pool«Покадровый классификатор»Запустить 2D CNN на каждом выбранном кадре, усреднить признаки по времени и классифицировать
3D-свёртка«Пространственно-временное ядро»Ядро выполняет свёртку по (T, H, W); может нативно моделировать движение
Раздувание (inflation)«Поднять 2D-веса до 3D»Инициализировать веса 3D-свёртки повторением весов 2D-свёртки вдоль новой временной оси, затем разделить на kernel_T для сохранения масштаба активаций
(2+1)D«Факторизованная свёртка»Разделить 3D на пространственную 2D и временную 1D; меньше параметров, дополнительная нелинейность между ними
Разделённое внимание«Сначала время, затем пространство»Блок трансформера с двумя механизмами внимания на слой: один по токенам в одном кадре, другой по токенам в одинаковой позиции
Клип«Окно из T кадров»Выбранная подпоследовательность T кадров; единица входа видеомодели
Точность клипа и видео«Два режима оценки»Клип = один образец из видео, видео = среднее по нескольким выбранным клипам
Kinetics«ImageNet для видео»400–700 классов действий, более 300 тыс. клипов YouTube, стандартный корпус для предобучения видео

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


Источник: Video Understanding — Temporal Modeling 04.11 — Stable Diffusion — Architecture & Fine-Tuning · Фаза 04 — Компьютерное зрение · 04.13 — 3D Vision — Point Clouds & NeRFs · Полный каталог