Как мы можем создавать видео для развлечения?

Генеративное машинное обучение - это круто, это факт. Мы можем создавать забавный текст и делать с изображениями всякую всячину. Это включает в себя создание любого количества чизбургеров с высоким разрешением. Однако видеоданные - это еще один зверь.

Для создания видео интуитивно понятным технологическим ответом также будет GAN. Допустим, мы хотим создать больше видео с котиками. Мы могли бы взять все видео с кошками с YouTube в качестве обучающих данных и заставить генератор и дискриминатор сражаться целую вечность, пока первый не создаст реалистичные видео с кошками.

К сожалению, мы еще не здесь. В какой-то момент мы, вероятно, увидим YoutubeGAN от Google, но он, вероятно, будет использовать для обучения миллионы TPU-часов вычислений. С другой стороны, мы сможем создавать бесконечное количество видеороликов о кошках. Ага!

А пока что с нашим единственным игровым графическим процессором, что мы, смертные, можем?

Прогнозирование следующего кадра

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

Для создания видео:

  1. Найдите крутое видео (оно должно быть простым и предсказуемым)
  2. Обучите модель предсказывать будущий кадр на основе прошлого кадра (ов)
  3. Выберите исходное изображение и запустите цикл обратной связи
    , т.е. спрогнозируйте следующий кадр, используйте его в качестве нового ввода и т. Д.
  4. Создайте видео с сгенерированными кадрами

Самая сложная часть - это, очевидно, этап обучения, какую модель мы должны использовать?

Pix2Pix

Вы, наверное, уже знакомы с pix2pix, это универсальная архитектура преобразования изображения в изображение швейцарский нож за edge2cat, черно-белое изображение в цветное, день в ночь, ...

Вы знаете, что сейчас есть Edge2pikachu? Вы действительно не можете остановить прогресс.

Говоря о прогрессе, вот очень личный график GAN-paper, если вам интересно, как мы сюда попали:

Использование pix2pix для предсказания следующего кадра

Pix2pix (с разными поворотами) использовался несколькими людьми для создания видео. Самый известный пользователь (и, может быть, изобретатель такого использования?) - Марио Клингеманн. Одна работа, в частности, попала в новости, его генеративный фейерверк. Этот парень потрясающий, я настоятельно рекомендую вам подписаться на него в твиттере (Марио Клингеманн).

Пошаговое руководство по созданию видео с помощью pix2pixHD

Для обучения нашей модели мы собираемся использовать реализацию PyTorch архитектуры pix2pixHD от Nvidia. Все необходимое есть в моей вилке проекта:

git clone -b video https://github.com/jctestud/pix2pixHD.git

pix2pixHD предназначен для приема большого количества информации о входном изображении (например, карты меток, которая определяет, где находятся пешеходы, автомобили и т. д.)

Нам это не нужно. В нашем случае это будет довольно просто:

  • в качестве входных данных мы будем использовать изображение RGB
  • в качестве вывода мы также будем использовать изображение RGB (следующий кадр)

Примечание: генератор имеет крайне плохой контекст (только один прошедший кадр, чтобы предсказать следующий), но он вроде как работает с простым движущимся видео.

В этом пошаговом руководстве я буду использовать следующее видео о пожаре. Он длится всего 1 минуту, но он справится со своей задачей: https://vimeo.com/62740159

Начнем с извлечения кадров из видео:

python3 extract_frames.py -video ~/Downloads/fire.mp4 -name fire_dataset -p2pdir . -width 1280 -height 736

Примечание. Для сетевой архитектуры требуются размеры изображения, кратные 32. Чем ближе мы можем приблизиться к разрешению 720p, тем больше будет 1280x736. По умолчанию мой сценарий будет пытаться извлекать кадры таким образом.

Давайте теперь обучим модель для одной эпохи (один проход по всему видео):

python3 train_video.py --name fire_project --dataroot ./datasets/fire_dataset/ --save_epoch_freq 1 --ngf 32

Примечание. Мой код генерирует пары изображений на лету. Чтобы посмотреть, что на самом деле сгенерировано, добавьте флаг «отладка».

Кроме того, вариант «ngf», который я использую, является одним из многих приемов, которые вы можете попробовать, чтобы уменьшить потребление памяти графическим процессором алгоритмом (чтобы, надеюсь, он поместился на 12 ГБ или даже 8 ГБ графического процессора)

Теперь вы можете создать видео с только что сохраненной контрольной точкой веса:

python3 generate_video.py --name fire_project --dataroot ./datasets/fire_dataset/ --fps 24 --ngf 32 --which_epoch 1 --how_many 200

Примечание: в этом примере мы генерируем 200 кадров размером 1280x736. Затем сценарий использует первые 60 кадров исходного видео (60-й кадр служит начальным значением для цикла обратной связи) и добавляет 200 сгенерированных кадров для создания видео с разрешением 1280x720 - 24 кадра в секунду.

В моем случае я получаю следующее:

Теперь оставьте свой графический процессор в покое на пару часов. Затем вернитесь и оцените, как быстро pix2pixHD только что научился генерировать пламя:

Примечание: для создания такого видео используется следующая команда:

python3 generate_progress_video.py --name fire_project --dataroot ./datasets/fire_dataset/ --fps 24 --ngf 32 --pstart 1 --pstop 47

Уловка по расписанию - для большей стабильности (в теории)

Пока искал похожие проекты (спойлер: код обычно недоступен), кто-то указал мне на недавний проект генерации видео, который является частью Magenta от Google. Автор, Дэмиен Генри, использует оригинальную архитектуру pix2pix (точнее, порт тензорного потока) для создания видео.

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

Этот трюк вдохновлен этой статьей: Запланированная выборка для прогнозирования последовательности с помощью рекуррентных нейронных сетей, Сами Бенжио и др., 2015

В статье идея тестируется на последовательностях символов и RNN, но она применяется непосредственно к кадрам. Вкратце, идея состоит в том, чтобы случайным образом (умный случайный) использовать поддельные входные данные (генерируемые генератором / моделью) для построения обучающих пар. Заставив модель научиться переходить от расходящегося прогноза на шаге ‹t› к наземной истине на шаге ‹t + 1›, мы можем принудить ее к автокоррекции или узнать, как вернуться на правильный путь, и в конечном итоге это может стабилизировать генеративный процесс.

Примечание: расходящийся ввод может исходить от одной или нескольких рекурсий в генераторе.

Вот пример с фреймами:

Традиционно в процессе обучения в качестве ввода / вывода используются пары реальных изображений, например A-C. В запланированном обучении выборки вы также используете сгенерированные поддельные изображения в качестве входных данных и строите пары, такие как B-C.

В моей (простой) реализации все делается на лету в цикле обучения. При итерации видео каждый раз, когда мы выполняем прямой проход, сгенерированное поддельное изображение сохраняется. На следующем шаге будет 1/2 (настраиваемая) вероятность выбора в качестве входных данных последнего сгенерированного кадра. С такой конфигурацией «броска костей» у вас есть 1/4 шанса использовать вторую рекурсию в качестве входных данных, 1/8 шанса использовать третью рекурсию и т. Д.

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

Запланированный отбор проб на практике

Результаты не обязательно так интересны, как идея (в моем случае). Иногда он вообще не работает, иногда (?), Но затем он производит некоторые (запланированные?) Движения отката, которые устраняют часть безумия, которое нам нравится в генеративном ML. Хотелось бы, чтобы я лучше разбирался в этих сбоях, но тестирование и настройка пользовательских архитектур требует очень много времени ...

Но вот один интересный пример, чтобы закончить на более позитивной ноте.

Давайте использовать входное видео с некоторой стабильной пространственной структурой, которую мы не хотим терять. В данном случае берег реки.

Команда обучения (с включенной выборкой по расписанию) следующая:

python3 train_video.py --name water_project --dataroot ./datasets/water_dataset/ --save_epoch_freq 1 --ngf 32 --scheduled_sampling --serial_batches

Вот результаты:

Мы ясно видим роль планового отбора проб. В модели SS-ON камни никогда не исчезают, и вода все еще течет (как бы) сквозь них, это весело :)

Модель SS-free тоже по-своему забавна, когда она представляет собой движущиеся береговые линии, похожие на траву.

Будущая работа :)

Если найду время, то я бы хотел:

  • сделайте все более стабильным (каждая контрольная точка настолько отличается, что я схожу с ума ...)
  • начать расследование переобучения,
  • попробуйте другие архитектуры, особенно те, которые созданы специально для генерации видео. Я думаю о недавнем проекте vid2vid (очевидно, Nvidia).

В любом случае, код доступен, если вы хотите поэкспериментировать или внести свой вклад. Повеселись!

(БОНУС) Создание фейерверков!

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

Я также вручную увеличивал масштаб во время цикла обратной связи.
Это то, что создает эффект «Тысячелетнего сокола».
Как интересный побочный эффект, он также немного будит модель :)

Вот и все. Если вам понравилось, подпишитесь на меня в Medium или Twitter, чтобы быть в курсе последних новостей!