Video-to-Video Synthesis
🔗 Ссылки
https://arxiv.org/abs/1808.06601
https://github.com/NVIDIA/vid2vid — оригинальный репозиторий
https://github.com/NVlabs/imaginaire — актуальный репозиторий
NeurIPS 2018 (тут есть supplementary material)
💎 Контрибьюшн
Это первое решение для conditional-генерации видео, работающее стабильно по времени. Зачем это вообще может быть нужно:
- Дешёвая генерация обучающей выборки в робототехнике (это предложили авторы, на мой взгляд немного сомнительно)
- Дипфейки
Авторы предложили достаточно общий фреймворк для синтеза видео на основе семантических данных — карт сегментации, скетчей лица или поз человека.
- Достаточно долгие стабильные видео — есть тест на 1200 кадров
- Высокое разрешение — 2048x1024 для Cityscapes
- Влияние на семантику — например, можно поменять метку класса на карте сегментации, и вместо деревьев нарисовать дома
- Мультимодальность — предложен метод, как для одного входа получать разные консистентные результаты. Например, можно заменить асфальтовую дорогу на брусчатку
🛠 Задача
Нужно построить алгоритм, который на основе семантических данных сможет генерировать видео, соответствующее семантике. Видео должно быть стабильно по времени.
В терминах статистики задача формулируется так: условное распределение синтезированных видео должно совпадать с условным распределением реальных видео при условии одних и тех же семантических данных:
Такая постановка хорошо ложится на GAN'ы, при стандартном обучении которых минимизируется JS-divergence между распределениями.
Для удобства предполагается, что кадры удовлетворяют условию Маркова:
Это позволяет генерировать их последовательно, вызывая генератор рекурсивно от уже сгенерированных кадров
🔎 Детали
1. Генератор
В генераторе используется модуль оценки Optical Flow (OF) w, чтобы варпить предыдущий кадр в текущий. Для заполнения окклюженов используется soft-маска m, чтобы справляться с размытыми объектами (близкие к камере, быстро двигающиеся) — когда варпишь размытый объект, он становится ещё более размытым, и для этого надо немножко дорисовать его текстуру. Для оценки OF и маски используются одни и те же веса, кроме последнего слоя. Сами окклюжены заполняются тем, что генерирует свёрточный генератор h.
Параметр L отвечает за то, сколько предыдущих кадров используется для генерации текущего. L = 1 — приводил к временной нестабильности, а L > 2 — забивал всю память (в 2018 году V100 были на 16GB), поэтому авторы остановились на L = 2
2. Foreground-background Prior
В случае Cityscapes можно заметить, что изображение делится на фон и объекты переднего плана. При этом преобразование фона от кадра к кадру хорошо задаётся глобальным преобразованием через OF, в то время как для объектов OF вычисляется неточно. Чтобы использовать это знание, делается декомпозиция с учётом background mask:
Сеть h_F, генерирующая объекты переднего плана, зависит только от семантических данных, но не от предыдущих кадров.
Для генерации высокого разрешения используется coarse-to-fine подход:
3. Дискриминатор
Использование нескольких дискриминаторов позволяет уменьшить проблему mode collapse. Используется 2 основных вида:
- Картиночный D_I — помогает каждому отдельному кадру выглядеть реалистично. Сравнивает кадры как картинки. Архитектура — multi-scale PatchGAN
- Видео-дискриминатор D_V — убеждается в правильности моделирования динамики. Он сравнивает последовательности кадров. Архитектура — тоже PatchGAN, с прореживанием кадров по времени (каждый k-й) для учёта разных временных зависимостей
Для обучения модуля OF используется FlowNet2 в качестве GT, а лосс сравнивает сами вектора OF и результат варпинга:
Для стабилизации и ускорения сходимости дополнительно добавлен FM-лосс, и в качестве экстракторов используются сами дискриминаторы + предобученная VGG.
В качестве GAN-лосса используется модификация LSGAN
4. Мультимодальность
Чтобы обеспечить мультимодальность, нужна instance segmentation map для входных кадров.
Дополнительно учится энкодер, который генерирует фичемапу размером с картинку и d каналами (d = 3). Затем происходит усреднение векторов в фичемапе для каждого объекта (размер фичемапы не меняется, но теперь во всех "пикселях" одного объекта одинаковые векторы). Эта фичемапа конкатенируется с семантическими данными и подаётся на вход в генератор.
После завершения обучения на векторах объектов одного класса фитится GMM, из которой на инференсе сэмплируются вектора для фичемапы. Это и позволяет влиять на содержание итоговой картинки.
Пример: в Cityscapes под меткой "дорога" есть асфальтовая дорога и брусчатка. После того, как мы зафитим GMM на 2 класса для "дороги", можно выбирать, что синтезировать:
5. Обучение
- DGX1 (8 x V100, 16GB каждая)
- 40 эпох
- ADAM (0.5, 0.999)
- LR = 0.0002
- 10 дней для 2K
- 512 -> 1024 -> 2048 (height = width / 2)
- Cityscapes: 2975 видео по 30 кадров = 89 250 кадров в обучении
- FaceForensics: 704 + 150 видео
- Apolloscape: 73 видео по 100–1000 кадров, половина для обучения
- Dance video: видео с YouTube по 3–4 мин. (4500–6000 кадров?), 512x720
🔬 Эксперименты
- FID по всем кадрам всех видео в валидации, вычисленный с помощью 2 сетей: ResNeXt и I3D
- Human Preference Score — SbS-сравнение из 2 вариантов, 10 респондентов
Неожиданно, но предложенный метод оказался лучшим по всем метрикам. Из ablation study видно, что меньше всего к качеству докидывает flow-warping модуль, а больше всего — conditional video discriminator. Также авторы заявляют, что при замене оценённого OF на GT визуальное качество не меняется, что говорит об устойчивости генератора к ошибкам в OF
Авторы пишут, что их алгоритм не справляется в некоторых ситуациях, например, при отрисовывании поворачивающей машины. Возможно, это можно исправить добавлением пространственной информации типа карт глубины
🍺 Заметки на полях
Тут будет небольшая выжимка о том, какие приколы есть в коде, но которые не описаны в статье.
Так получилось, что я много копался в старом коде vid2vid, который был выложен в момент публикации статьи. Тогда ещё не было DistributedDataParallel, поэтому он содержит много грязных хаков, как заставить всё работать быстро и параллельно на 8 карточек (старый DataParallel умеет только в 4 карточки с копированием на мастер-ноду для бэкпропа). Да и в целом архитектурно код там не самый приятный. В новом репозитории imaginaire, где собран зоопарк conditional-моделей, всё гораздо лучше, моднее и современнее.
Итак, во-первых, fine-scale-генератор фризится на первые несколько эпох. Это логично, но ниоткуда не следует.
Во-вторых, по умолчанию бэкпроп делается только по одному кадру. Для изменения этого поведения есть параметр max_frames_backpropagate. Если указать значение >1, то количество кадров, через которые проходит бэкпроп, будет линейно увеличиваться до этого значения.
Во-третьих, как бы вы решали проблему первого кадра, если сетка всегда принимает на вход L=2 предыдущих? Правильно, можно не решать никак, и начинать генерировать с сразу третьего. Ведь семантическую информацию мы откуда-то взяли — значит есть и исходное видео.
Ну а если очень хочется? Тогда обучается отдельная сетка, которая генерирует только первый кадр, и к ней не применяется видео-дискриминатор.
В-четвёртых, удивление вызвало то, что для генерации лиц из скетчей на вход приходит фичемап с 15 каналами, а не одноканальная картинка с чертами лица. Видимо для лучшего кондишенинга в остальные 14 каналов записаны карты, получающиеся после применения Distance Transform к каждой части лица (глаза, нос, рот и т.д.).
В-пятых, для апскейла в генераторе используется устаревшая схема с deconvolution-слоями, которая приводит к шахматке при генерации:
Это известная проблема, она решается заменой deconv на nearest upsample + conv.
В остальном это действительно мощный и гибкий фреймворк, позволяющий синтезировать качественные консистентные видеоролики и использовать разные типы семантической информации на входе.