Я сгенерил новый датасет на 49.5k изображений в разрешении 1920х1080, в сжатом состоянии получилось около 95.5GB, больше не смог, закончилась память на диске в процессе создания 😭. Чтобы автоматизировать создание датасета я использовал следующий пайплайн: запускаем comfyui сервер на нужном порте и карте, а потом при помощи python скрипта посылаем запросы к нему, предварительно автоматически меняя пути к картинкам в отсылаемом json пайплайне. Так как генерация этого датасета заняла около 2 дней, то без запуска обработки в фоне, я бы устал фиксить случайные ошибки в результате разрыва соединения и тд. в общем мастхев для длительных тасок. Местами изображения получились ABSOLUTE CINEMA.
Потом я попробовал снова обучить InstructPix2Pix, подождал 10631 шагов с batch_size=4, gradient_accumulation_steps=8 (график обучения тут, модель тут, код запуска тут). Однако к сожалению на инференсе изображения получаются слишком засвеченными с количеством шагов в 20-30, а что-то нормальное получается после 100. Так что возможно в прошлый раз, дело было не в количестве данных. Но после применения LCM, нормальная картинка стала появлятся уже после 15 шагов(реалтаймом тут не пахнет). Короч больше вопросов чем ответов. Но есть и плюсы, версия которая дистиллировала исходный пайплайн уменьшила деформацию объектов, но добавила мигание(думаю тому причиной LCM). Главная ценность данного эксперимента в том что используя подобные методы я могу получить практически идентичную картинку более малой моделью без использования кенни фильтров, нормал мапов, ip адаптеров, лор, контролнетов и прочего. Просто img2img. Прикладываю видео с использованием LCM.
Потом я попробовал снова обучить InstructPix2Pix, подождал 10631 шагов с batch_size=4, gradient_accumulation_steps=8 (график обучения тут, модель тут, код запуска тут). Однако к сожалению на инференсе изображения получаются слишком засвеченными с количеством шагов в 20-30, а что-то нормальное получается после 100. Так что возможно в прошлый раз, дело было не в количестве данных. Но после применения LCM, нормальная картинка стала появлятся уже после 15 шагов(реалтаймом тут не пахнет). Короч больше вопросов чем ответов. Но есть и плюсы, версия которая дистиллировала исходный пайплайн уменьшила деформацию объектов, но добавила мигание(думаю тому причиной LCM). Главная ценность данного эксперимента в том что используя подобные методы я могу получить практически идентичную картинку более малой моделью без использования кенни фильтров, нормал мапов, ip адаптеров, лор, контролнетов и прочего. Просто img2img. Прикладываю видео с использованием LCM.
👍1
После этого я понял что нужно двигаться в сторону одношаговой pix2pix диффузии. Одна из таких работ это img2img-turbo. Данная работа использует stabilityai/sd-turbo, одношаговый DDPMScheduler и (к сожалению) немного измененную архитектуру форварда vae со skip connections. К сожалению, потому что это сделало его несовместимым по умолчанию с torch compile и другими решениями по ускорению. Думаю попробовать вообще выкинуть его. Попробовал обучить его с batch_size=2 gradient_accumulation_steps=16 количество шагов 7263. Вроде бы как на трейне, если смотреть на картинки в графике обучения, то сходство почти идеальное. Но вроде как после 5000 не было смысла больше ждать. Единственное что меня смущает это она не выучивает мелкие детали(например листвы) что немного портит картинку. Однако данная модель полностью пофиксила тряску и деформацию тестового и тренировочного датасета. Далее привожу пример запуска: bfloat16, float32 на тесте, float32 на трейне. float32 как по мне лучше, конечно, я же в нем учил :)
Насчет реалтайма из коробки тут намного лучше, на данный момент она работает в 15.6 fps на 4090. Примерно столько мне выдает StreamDiffusion в eager mode, а в tensorrt с похожей моделью 33 fps, что в 3 раза меньше чем они заявляют. Наверное дело в изменившемся API tensorrt, надо дебажить. Модель работает медленно, как это обычно бывает, скорее всего дело из-за излишнего оверхеда со стороны вызова cuda kernels, надо прочекать модель на graph breaks и переписать нормально на torch compile. Также во всех этих моделях используется текстовый энкодер(мне он не нужен совсем, поэтому его надо выкинуть), а также unet с обуславливанием на данные скрытые состояния от энкодера. Я пока мало разбираюсь в мат части, но почему нельзя заменить unet на скажем squeezenet или MobileNetV3, а vae на TAESD? Наверное на то есть причины... Что ж, следующий этап это изучение графика вызовов cuda kernels.
Насчет реалтайма из коробки тут намного лучше, на данный момент она работает в 15.6 fps на 4090. Примерно столько мне выдает StreamDiffusion в eager mode, а в tensorrt с похожей моделью 33 fps, что в 3 раза меньше чем они заявляют. Наверное дело в изменившемся API tensorrt, надо дебажить. Модель работает медленно, как это обычно бывает, скорее всего дело из-за излишнего оверхеда со стороны вызова cuda kernels, надо прочекать модель на graph breaks и переписать нормально на torch compile. Также во всех этих моделях используется текстовый энкодер(мне он не нужен совсем, поэтому его надо выкинуть), а также unet с обуславливанием на данные скрытые состояния от энкодера. Я пока мало разбираюсь в мат части, но почему нельзя заменить unet на скажем squeezenet или MobileNetV3, а vae на TAESD? Наверное на то есть причины... Что ж, следующий этап это изучение графика вызовов cuda kernels.
🔥7
Реалтайм диффузия в 100fps.
Именно столько выдает на данный момент связка 4090+ultra 7 265k при запуске диффузии на 512х512 и hidden size 64.
Я взял taesd, а из unet выкинул все модули с attention и заменил все на convolution. Также диффузия является одношаговой, то есть мы просим сгенерировать картинку сразу. Получается такой пайплайн. vae.decode(scheduler.step(unet(vae.encode(image)))). Scheduler я использую пока что тот, что был в работе pix2pix turbo DDPMScheduler. Вероятно его смена тоже может улучшить изображение. Для компиляции vae, unet использовал stable-fast.
Замеряю этим кодом. Картинки уже преобразованы и лежат в оперативке на CPU (это момент когда я буду их получать из буфера в reshade), потом перевожу ее в CUDA, однако если представить что все картинки сразу в CUDA тогда будет 191 FPS! С учетом того что играбельность начинается с 20 fps, вполне норм.
Сначала запустил обучение на dim/nfs_pix2pix_1920_1080_v6, wandb, 15_000 шагов, в целом результат удовлетворительный, модель почти идеально научилась воспроизводить обучающую выборку, несмотря на то что я существенно сократил размер модели и выкинул attention слои. Примеры можно посмотреть в wandb. Скачать тут dim/nfs_pix2pix_1739912522
Однако потери есть. Так как изначальные картинки мутные и детали там не явно выражены, при обучении, микродетали теряются и картинка получается мыльной. На итоговом видео это выглядит уже как просто перекраска, а не ремастер. Тогда я решил улучшить качество данных, сделав апскейл двойным прогоном. workflow. Долгое время пытался заставить апскелить FLUX, но сдался и все сделал на RealVisXL_V4.0_Lightning. Примеры выше\ниже хз где телега их разместит.
Теперь точно можно сказать что картинка улучшилась, причем такого качества точно никогда не достичь обычными рукописными алгоритмами или же основанные на простых функциях. Данные решают. Сделал 2 варианта датасета, то что получается после 1 аскейла и 2. Данные тут dim/nfs_pix2pix_1920_1080_v5_upscale_1x_raw dim/nfs_pix2pix_1920_1080_v5_upscale_2x_raw искать на https://huggingface.co/datasets. К сожалению я пока не понял почему теряется качество при сохранении и можно этого как-то избежать, поэтому также выложил просто пожатые архивы render_nfs_4screens_5_sdxl_1_upscale_1x_raw.tar.gz и render_nfs_4screens_5_sdxl_1_upscale_2x_raw.tar.gz. У данных апскейлов есть галлюцинации на объектах в далеке, которые я не стал фиксить. Апскейл 852 картинок занял примерно 36-48 часов на одной 4090. Делать батчами, ускорять и тд не пробовал.
После обучения на dim/nfs_pix2pix_1920_1080_v5_upscale_2x_raw wandb картинки стали четче. Теперь думаю можно сказать что модель не справляется. Наверное нужна другая архитектура, например Sana. Скачать тут dim/nfs_pix2pix_1740323104
Что видео? На мой взгдят картинка стала хуже. Из-за нестабильной картинки в апскейле, в далеке мы получаем кашу как и в оригинале. Однако если закрыть глаза ровно по середине можно понять что уже не так все плохо. Проблема в данных.
Как бы мне не хотелось разбираться с нейронками, так как не совсем понятны ограничения конечного пайплайна, думаю внедрить нейронки что есть end2nd, чтобы была возможность поиграть. А потом уже запустить ресерч по поиску архитектур, улучшению данных и тд.
Кстати базовый код на С++ уже готов, https://github.com/dmitrymailk/reshade/blob/main/examples/01-framerate_limit%20copy/negative_filter.cpp. Он меняет цвета картинки на противоположные. Тестил только на 3050ti, когда все выключено 90fps, когда код просто выполняет загрузку картики в массив, а потом обратно возвращает ее в пайплайн(короч ничего не делает над картинкой), тогда 72fps. Если же я включаю фильтр 50fps (правильно фильтр это просто 2 вложенных цикла). Теперь нужно как-то вместо данного цикла воткнуть нейронку.
Именно столько выдает на данный момент связка 4090+ultra 7 265k при запуске диффузии на 512х512 и hidden size 64.
Я взял taesd, а из unet выкинул все модули с attention и заменил все на convolution. Также диффузия является одношаговой, то есть мы просим сгенерировать картинку сразу. Получается такой пайплайн. vae.decode(scheduler.step(unet(vae.encode(image)))). Scheduler я использую пока что тот, что был в работе pix2pix turbo DDPMScheduler. Вероятно его смена тоже может улучшить изображение. Для компиляции vae, unet использовал stable-fast.
Замеряю этим кодом. Картинки уже преобразованы и лежат в оперативке на CPU (это момент когда я буду их получать из буфера в reshade), потом перевожу ее в CUDA, однако если представить что все картинки сразу в CUDA тогда будет 191 FPS! С учетом того что играбельность начинается с 20 fps, вполне норм.
import time
amount = 400
start = time.time()
for image in images[:amount]:
output_image = model(image.cuda())
total = time.time() - start
print(f"total {total}s, {total/amount}s per img {1/(total/amount)}fps")
# total 4.003062725067139s, 0.010007656812667846s per img 99.92349045524668fps
Сначала запустил обучение на dim/nfs_pix2pix_1920_1080_v6, wandb, 15_000 шагов, в целом результат удовлетворительный, модель почти идеально научилась воспроизводить обучающую выборку, несмотря на то что я существенно сократил размер модели и выкинул attention слои. Примеры можно посмотреть в wandb. Скачать тут dim/nfs_pix2pix_1739912522
Однако потери есть. Так как изначальные картинки мутные и детали там не явно выражены, при обучении, микродетали теряются и картинка получается мыльной. На итоговом видео это выглядит уже как просто перекраска, а не ремастер. Тогда я решил улучшить качество данных, сделав апскейл двойным прогоном. workflow. Долгое время пытался заставить апскелить FLUX, но сдался и все сделал на RealVisXL_V4.0_Lightning. Примеры выше\ниже хз где телега их разместит.
Теперь точно можно сказать что картинка улучшилась, причем такого качества точно никогда не достичь обычными рукописными алгоритмами или же основанные на простых функциях. Данные решают. Сделал 2 варианта датасета, то что получается после 1 аскейла и 2. Данные тут dim/nfs_pix2pix_1920_1080_v5_upscale_1x_raw dim/nfs_pix2pix_1920_1080_v5_upscale_2x_raw искать на https://huggingface.co/datasets. К сожалению я пока не понял почему теряется качество при сохранении и можно этого как-то избежать, поэтому также выложил просто пожатые архивы render_nfs_4screens_5_sdxl_1_upscale_1x_raw.tar.gz и render_nfs_4screens_5_sdxl_1_upscale_2x_raw.tar.gz. У данных апскейлов есть галлюцинации на объектах в далеке, которые я не стал фиксить. Апскейл 852 картинок занял примерно 36-48 часов на одной 4090. Делать батчами, ускорять и тд не пробовал.
После обучения на dim/nfs_pix2pix_1920_1080_v5_upscale_2x_raw wandb картинки стали четче. Теперь думаю можно сказать что модель не справляется. Наверное нужна другая архитектура, например Sana. Скачать тут dim/nfs_pix2pix_1740323104
Что видео? На мой взгдят картинка стала хуже. Из-за нестабильной картинки в апскейле, в далеке мы получаем кашу как и в оригинале. Однако если закрыть глаза ровно по середине можно понять что уже не так все плохо. Проблема в данных.
Как бы мне не хотелось разбираться с нейронками, так как не совсем понятны ограничения конечного пайплайна, думаю внедрить нейронки что есть end2nd, чтобы была возможность поиграть. А потом уже запустить ресерч по поиску архитектур, улучшению данных и тд.
Кстати базовый код на С++ уже готов, https://github.com/dmitrymailk/reshade/blob/main/examples/01-framerate_limit%20copy/negative_filter.cpp. Он меняет цвета картинки на противоположные. Тестил только на 3050ti, когда все выключено 90fps, когда код просто выполняет загрузку картики в массив, а потом обратно возвращает ее в пайплайн(короч ничего не делает над картинкой), тогда 72fps. Если же я включаю фильтр 50fps (правильно фильтр это просто 2 вложенных цикла). Теперь нужно как-то вместо данного цикла воткнуть нейронку.
GitHub
GitHub - chengzeyi/stable-fast: https://wavespeed.ai/ Best inference performance optimization framework for HuggingFace Diffusers…
https://wavespeed.ai/ Best inference performance optimization framework for HuggingFace Diffusers on NVIDIA GPUs. - chengzeyi/stable-fast
👍3🤡2❤1
Media is too big
VIEW IN TELEGRAM
У меня наконец получилось подружить диффузию с reshade.
По итогу получился совершенно проклятый код. Пайплайн получился примерно следующий. Сначала создается семафор на питоне который ждет пока его не тригернут, тем самым не закрывая программу на python. Далее на основе с++ API reshade, получаю доступ к backbuffer, сохраняю данную картинку в промежуточный массив. Создаю shared memory в с++ для inter process communication с python. Далее копирую изображение в shared memory и тригерю питоновский семафор, одновременно вешая другой семафор в с++ который ожидает пока его не тригернут из python. В самом питоне уже просто запихиваю данное изображение в pytorch через протокол buffer. Далее как обычно передают изображение в нейронку, результат сохраняю в shared memory, тригерю семафор для с++.
Зачем так проклято? Насколько я понял, моя игра работает в х32, и если я соберу addon для reshade в х64, он просто не увидит его и ничего не заработает. Зачем нужен х64? Только в нем работают нейронки на питоне да и большинство программ для их внедрения больше всего любят х64. К сожалению я узнал это только когда написал обертку для pybind, которая запускает интерпретатор питона из с++ и умеет импортировать любые модули для их дальнейшего использования, но это работает только с x32 питоном.
Из грустных новостей у меня так и не получилось поставить stable fast на windows, и вообще с нейронками на windows больно работать. Поэтому прилось запускать ее на голом торче, что дает на моем железе 70fps. Однако самый главный фактор который роняет фпс в игре оказалась не нейронка, а копирование картиночного массива туда-сюда. Из мыслей как это можно исправить это как-то уйти от перегонки с CPU на GPU, или хотябы данные массивы сделать shared memory.
Насчет конечного результата для пользователя пока не все так хорошо, картинка слишком убогая, потому что изначальаня задумка была для того чтобы картинка стала как в апскейлах, которые я показывал в прошлый раз. Результат можно посмотреть на ютубе или тут.
Код для аддона пока что лежит тут. Из интересного появилась новая restyle фича от runway, которая в теории должна помочь с генерацией синтетики для обучения.
По итогу получился совершенно проклятый код. Пайплайн получился примерно следующий. Сначала создается семафор на питоне который ждет пока его не тригернут, тем самым не закрывая программу на python. Далее на основе с++ API reshade, получаю доступ к backbuffer, сохраняю данную картинку в промежуточный массив. Создаю shared memory в с++ для inter process communication с python. Далее копирую изображение в shared memory и тригерю питоновский семафор, одновременно вешая другой семафор в с++ который ожидает пока его не тригернут из python. В самом питоне уже просто запихиваю данное изображение в pytorch через протокол buffer. Далее как обычно передают изображение в нейронку, результат сохраняю в shared memory, тригерю семафор для с++.
Зачем так проклято? Насколько я понял, моя игра работает в х32, и если я соберу addon для reshade в х64, он просто не увидит его и ничего не заработает. Зачем нужен х64? Только в нем работают нейронки на питоне да и большинство программ для их внедрения больше всего любят х64. К сожалению я узнал это только когда написал обертку для pybind, которая запускает интерпретатор питона из с++ и умеет импортировать любые модули для их дальнейшего использования, но это работает только с x32 питоном.
Из грустных новостей у меня так и не получилось поставить stable fast на windows, и вообще с нейронками на windows больно работать. Поэтому прилось запускать ее на голом торче, что дает на моем железе 70fps. Однако самый главный фактор который роняет фпс в игре оказалась не нейронка, а копирование картиночного массива туда-сюда. Из мыслей как это можно исправить это как-то уйти от перегонки с CPU на GPU, или хотябы данные массивы сделать shared memory.
Насчет конечного результата для пользователя пока не все так хорошо, картинка слишком убогая, потому что изначальаня задумка была для того чтобы картинка стала как в апскейлах, которые я показывал в прошлый раз. Результат можно посмотреть на ютубе или тут.
Код для аддона пока что лежит тут. Из интересного появилась новая restyle фича от runway, которая в теории должна помочь с генерацией синтетики для обучения.
👍3❤1🤡1
Личные итоги года.
Ничего не делал по данному проекту последние 8 месяцев, занимался всем подряд. Например пытался понять как можно создать универсальный компрессор для текста чтобы по итогу модель кушала меньше токенов и генерировала больше текста. Спойлер, ничего практически значимого не вышло. Потом пытался разобраться как на малом скейле (4 A100 GPU) прям с нуля максимально эффективно делать претрейн модельки в 1B, при этом оставаясь в экосистеме transformers и библиотеке lm eval, делая эвалюацию прямо в моменте обучения. Если кому интересно код вот тут https://github.com/dmitrymailk/vision_genai/blob/master/train_gym/massive_train/pretrain_edu/pretrain_hf_trainer.py Наверное позже напишу более подробный пост, но пока я этим занимался случилась некоторая инфляция этих знаний, Карпатый(https://github.com/karpathy/nanochat) и команда SmolLM(The Smol Training Playbook: The Secrets to Building World-Class LLMs https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook) выпустила свои статьи про подобные запуски. Хотя на мой взгляд это не отменяет ценность моей репы. Еще попутно значительно ускорил recurrent memory transformer, но чет особо не пошло. Оставшуюся часть года занимался исследованием области Computer Use, точно потом сделаю обзор локальных моделей на конец 2025. Спойлер, довольно неплохая модель оказалась fara https://github.com/microsoft/fara в целом нормально себя чувствует на картах до 24 гб, и стабильно может выполнять очень простые действия в вебе. В целом планирую двигаться в этой области в следующем году, она как раз такая техничная и комплексная, как я люблю.
Ничего не делал по данному проекту последние 8 месяцев, занимался всем подряд. Например пытался понять как можно создать универсальный компрессор для текста чтобы по итогу модель кушала меньше токенов и генерировала больше текста. Спойлер, ничего практически значимого не вышло. Потом пытался разобраться как на малом скейле (4 A100 GPU) прям с нуля максимально эффективно делать претрейн модельки в 1B, при этом оставаясь в экосистеме transformers и библиотеке lm eval, делая эвалюацию прямо в моменте обучения. Если кому интересно код вот тут https://github.com/dmitrymailk/vision_genai/blob/master/train_gym/massive_train/pretrain_edu/pretrain_hf_trainer.py Наверное позже напишу более подробный пост, но пока я этим занимался случилась некоторая инфляция этих знаний, Карпатый(https://github.com/karpathy/nanochat) и команда SmolLM(The Smol Training Playbook: The Secrets to Building World-Class LLMs https://huggingface.co/spaces/HuggingFaceTB/smol-training-playbook) выпустила свои статьи про подобные запуски. Хотя на мой взгляд это не отменяет ценность моей репы. Еще попутно значительно ускорил recurrent memory transformer, но чет особо не пошло. Оставшуюся часть года занимался исследованием области Computer Use, точно потом сделаю обзор локальных моделей на конец 2025. Спойлер, довольно неплохая модель оказалась fara https://github.com/microsoft/fara в целом нормально себя чувствует на картах до 24 гб, и стабильно может выполнять очень простые действия в вебе. В целом планирую двигаться в этой области в следующем году, она как раз такая техничная и комплексная, как я люблю.
GitHub
vision_genai/train_gym/massive_train/pretrain_edu/pretrain_hf_trainer.py at master · dmitrymailk/vision_genai
Contribute to dmitrymailk/vision_genai development by creating an account on GitHub.
❤8🔥4🤡1
Желаю всем больше нейрослопа в ленте в этом году.
Последние месяц я решил возобновить работу над проектом. За время простоя вышло много видео моделей, лор и техник. Так как я сильно привязался к идее покадрового редактирования кадра, а затем его сглаживания, я продолжал копать в эту сторону. По итогу получился следующий пайплайн, общую идею которую я прочитал в ditto https://github.com/EzioBy/Ditto . Если очень кратко, их главная заслуга в том что они смогли очень сильно автоматизировать процесс создания датасета с инструкциями для редактирования видео. Припомощи WAN VACE и QWEN-EDIT, qwen редактирует ключевые кадры, а wan-vace уже на основе карты глубины выдает итоговое видео. Я поэкспериментировал с этим подходом, по итогу получился следующий алгоритм.
Этап 1: Первичная покадровая стилизация (SDXL)
На вход поступает последовательность кадров, независимо обработанных через SDXL.
Этап 2: Восстановление временной структуры (Wan VACE 14B)
Применяется модель VACE в режиме Masked Video-to-Video (MV2V).
Берется 250 кадров. Фиксирую по маске каждый 16-й кадр. Все промежуточные кадры стартуют свою генерацию со стилизованных изображений. Ключевое отличие тут от стандартного использования VACE, я попробовал заменить карту глубины между этими кадрами на также стилизованные кадры и это позволило сохранить стиль напротяжении всего видео и пофиксить все серьезные ошибки мерцания и деформации объектов.
Этап 3: Устранение шума (SeedVR2)
Сглаженное видео передается в модель SeedVR2, специализирующуюся на реставрации видео. Она отлично убирает оставшиеся серьезные артефакты, которые остались от покадровой стилизации. Но, на моих данных она замыливает текстуры. Для этого их нужно добавить обратно.
Этап 4: Восстановление деталей (Wan Video 14B Video-to-Video)
Для возвращения текстур и исправления финальных темпоральных ошибок выполняется финальная обработка моделью Wan Video 14B в режиме Video-to-Video. Процесс генерации запускается с экстремально низким уровнем шумоподавления (denoise = 0.09) и ограничением в 2 шага (steps = 2). Значение CFG устанавливается на 1.0, сэмплер – uni_pc.
Этап 5: Восстановление текстуры дорожного полотна
Поскольку дорожное полотно занимает значительную часть кадра, потеря его детализации негативно сказывается на общем восприятии четкости видео. Для этого я при помощи florence-2 и SAM2 нахожу дорогу, смешиваю плавно по гауссу оригинальное изображение со сглаженным кадром. Тоже самое что я делал c VEnhancer.
На выходе мы имеем наконец, фактически идентичное общему стилю, с сохранением деталей из оригинального SDXL, плавное видео. На данном этапе я решил остановиться, я считаю этого пайплайна в целом достаточно для генерации неограниченного количества синтетики для обучения MVP.
Сейчас я сфокусировался на создании действительно качественной одношаговой диффузионки. В целом для этого в этом году вышли все работы: repa-e(end-to-end обучение диффузионки совместно с VAE), latent bridge matching(рабочая и многообещающая теория на замену flow matching), seedvr2(одношаговая диффузионка для реконструкции, которая много юзает из работы The GAN is dead; long live the GAN!), DMD2(и различные техники дистиляции), rectified flow(выпрямление решающих потоков), [TwinFlow](https://github.com/inclusionAI/TwinFlow) и тд. Просто на мой взгляд теперь надо создать end2end алгоритм который бы бесшовно адаптировал вот этот генерируемый набор кадров в качественный реалтаймовый фильтр для 4090, а затем и 4060 Laptop. Теперь это просто програмерская задачка по перебору гиперпараметров и переписыванию кода. Думаю что через пару месяцев буду ездить в NFS с фотореалистичной графикой с видеорегистраторов.
Последние месяц я решил возобновить работу над проектом. За время простоя вышло много видео моделей, лор и техник. Так как я сильно привязался к идее покадрового редактирования кадра, а затем его сглаживания, я продолжал копать в эту сторону. По итогу получился следующий пайплайн, общую идею которую я прочитал в ditto https://github.com/EzioBy/Ditto . Если очень кратко, их главная заслуга в том что они смогли очень сильно автоматизировать процесс создания датасета с инструкциями для редактирования видео. Припомощи WAN VACE и QWEN-EDIT, qwen редактирует ключевые кадры, а wan-vace уже на основе карты глубины выдает итоговое видео. Я поэкспериментировал с этим подходом, по итогу получился следующий алгоритм.
Этап 1: Первичная покадровая стилизация (SDXL)
На вход поступает последовательность кадров, независимо обработанных через SDXL.
Этап 2: Восстановление временной структуры (Wan VACE 14B)
Применяется модель VACE в режиме Masked Video-to-Video (MV2V).
Берется 250 кадров. Фиксирую по маске каждый 16-й кадр. Все промежуточные кадры стартуют свою генерацию со стилизованных изображений. Ключевое отличие тут от стандартного использования VACE, я попробовал заменить карту глубины между этими кадрами на также стилизованные кадры и это позволило сохранить стиль напротяжении всего видео и пофиксить все серьезные ошибки мерцания и деформации объектов.
Этап 3: Устранение шума (SeedVR2)
Сглаженное видео передается в модель SeedVR2, специализирующуюся на реставрации видео. Она отлично убирает оставшиеся серьезные артефакты, которые остались от покадровой стилизации. Но, на моих данных она замыливает текстуры. Для этого их нужно добавить обратно.
Этап 4: Восстановление деталей (Wan Video 14B Video-to-Video)
Для возвращения текстур и исправления финальных темпоральных ошибок выполняется финальная обработка моделью Wan Video 14B в режиме Video-to-Video. Процесс генерации запускается с экстремально низким уровнем шумоподавления (denoise = 0.09) и ограничением в 2 шага (steps = 2). Значение CFG устанавливается на 1.0, сэмплер – uni_pc.
Этап 5: Восстановление текстуры дорожного полотна
Поскольку дорожное полотно занимает значительную часть кадра, потеря его детализации негативно сказывается на общем восприятии четкости видео. Для этого я при помощи florence-2 и SAM2 нахожу дорогу, смешиваю плавно по гауссу оригинальное изображение со сглаженным кадром. Тоже самое что я делал c VEnhancer.
На выходе мы имеем наконец, фактически идентичное общему стилю, с сохранением деталей из оригинального SDXL, плавное видео. На данном этапе я решил остановиться, я считаю этого пайплайна в целом достаточно для генерации неограниченного количества синтетики для обучения MVP.
Сейчас я сфокусировался на создании действительно качественной одношаговой диффузионки. В целом для этого в этом году вышли все работы: repa-e(end-to-end обучение диффузионки совместно с VAE), latent bridge matching(рабочая и многообещающая теория на замену flow matching), seedvr2(одношаговая диффузионка для реконструкции, которая много юзает из работы The GAN is dead; long live the GAN!), DMD2(и различные техники дистиляции), rectified flow(выпрямление решающих потоков), [TwinFlow](https://github.com/inclusionAI/TwinFlow) и тд. Просто на мой взгляд теперь надо создать end2end алгоритм который бы бесшовно адаптировал вот этот генерируемый набор кадров в качественный реалтаймовый фильтр для 4090, а затем и 4060 Laptop. Теперь это просто програмерская задачка по перебору гиперпараметров и переписыванию кода. Думаю что через пару месяцев буду ездить в NFS с фотореалистичной графикой с видеорегистраторов.
GitHub
GitHub - EzioBy/Ditto: [CVPR'26 Highlight] Ditto: Scaling Instruction-Based Video Editing with a High-Quality Synthetic Dataset
[CVPR'26 Highlight] Ditto: Scaling Instruction-Based Video Editing with a High-Quality Synthetic Dataset - EzioBy/Ditto
❤4🔥3👍1
Media is too big
VIEW IN TELEGRAM
Отказался от использования костыльного решения с reshade. Теперь я напрямую использую захват экрана от windows API, передаю данную текстуру в cuda, затем в pipeline на tensorRT. Это в свою очередь позволяет достичь 56-60 кадров с одношаговой (VAE->UNET->VAE) на моей ноутбучной RTX 4060 и ryzen 9 7945HX на слегка заниженных частотах. Но это все хорошо с NFS, я пробовал запускать в dirt 3, dirt 2 colin mc rae, там 32-35 всего. С точки зрения пользователя это работает примерно так, запускаем игру, запускаем бинарник через консоль и выбираем нужное окно, и прога начинает захват. Затем можно нажать f9 и поверх целевого окна рисуется новое окно которое пропускает все инпуты в целевую прогу. Там я еще влепил RTX video super resolution, потому что 512х512 на моем 2к экране тяжело смотреть, просадка примерно 4-5 FPS, честно говоря вообще того не стоит лучше потом на какой нибудь nvidia image scaling или обычный бикубик. DLSS не внедрить, там нужно кучу внутряков от движка передавать, что противоречит моей философии основываться только на входной картинке.
Конечно я сейчас использую довольно жирный unet, но большее время занимает VAE. Сначала я использовал fal/FLUX.2-Tiny-AutoEncoder, но он слишком мылил и убивал детали в декодированной картинке, так что пришлось натренировать свою на целевых данных, что дало четкость и мелкие текстуры. Для этого юзаю слегка модифицированный https://github.com/cloneofsimo/vqgan-training.
К своему сожалению или облегчению я обнаружил что обучение на сглаженных картинках при помощи видеогенераторов не особо нужно в текущем сетапе обучения.
Благодаря тому что вышел flux klein 4B, можно обучить любую лору на редактирование. У меня уже был датасет гиперреалистичных изображений полученных при помощи двойного апскейла SDXL. Их главная проблема что в далеке они создают чудовищые искажения объектов что не подходит под задачу ремастера. Но для объектов вблизи и средней давности получается неплохо. Сначала я попробовал обучить лору на всем датасете без фильтрации артефактов, получилось идеально воспроизвести все ошибки и на тесте. отлично подумал я и завайбкодил за час инструмент для разметки данных, из 4к картинок меня устроило всего 241 dim/nfs_pix2pix_1920_1080_v6_upscale_2x_raw_filtered. Соответственно после обучения на нем результат стал значительно лучше на тестовых данных, которые модель раньше не видела. Но все равно осталась странная проблема со скачком цветов, логики генерации растительности и тд. Я списал это на проблему шума. Поэтому попробовал применить structured noise https://yuzeng-at-tri.github.io/ppd-page/ что значительно улучшило результаты и я уже точно могу сказать что сейчас проблема только в данных на которых тренирую лору(да в них еще есть артефакты на дальние автомобили и объекты). Интересный факт, лора обучаласть на размерность 1 на q,k,v и итоговая лора весит всего 503 килобайта. Килобайта ало. Сама модель конечно весит в BF16 7.75 GB, лора тут https://huggingface.co/dim/nfs_pix2pix_1920_1080_v6_upscale_2x_raw_filtered_noise_lora_1_klein_4B_512x512
В своих попытках снизить галлюцинации, я так все зарегулировал что модель превратилась в просто покрасочный фильтр, который не изменяет геометрию. Из плюсов максимально стабильная картинка без кипения, из минусов пропадает как таковой смысл модели, детальный асфальт или листву она не создает. Вообще я думал над дистиляцией или встройкой GAN, я пробовал r3gan и patch gan, но они в какой-то момент у меня взрываются, я не умею это готовить. Также начал разбирать reflow meanflow, piflow, twinflow, senseflow, но пока на уровне самих репозиториев, наверное это должно работать лучше. Еще думаю над Latent Adversarial Diffusion Distillation, ее вроде как stable diffusion использовали.
Теперь имея на руках прогу для реального инференса я могу сказать что такой размер модели это предел без каких-то хитрых кернелов или алгоритмов, зато понятно пространство перебора параметров и методов.
Конечно я сейчас использую довольно жирный unet, но большее время занимает VAE. Сначала я использовал fal/FLUX.2-Tiny-AutoEncoder, но он слишком мылил и убивал детали в декодированной картинке, так что пришлось натренировать свою на целевых данных, что дало четкость и мелкие текстуры. Для этого юзаю слегка модифицированный https://github.com/cloneofsimo/vqgan-training.
К своему сожалению или облегчению я обнаружил что обучение на сглаженных картинках при помощи видеогенераторов не особо нужно в текущем сетапе обучения.
Благодаря тому что вышел flux klein 4B, можно обучить любую лору на редактирование. У меня уже был датасет гиперреалистичных изображений полученных при помощи двойного апскейла SDXL. Их главная проблема что в далеке они создают чудовищые искажения объектов что не подходит под задачу ремастера. Но для объектов вблизи и средней давности получается неплохо. Сначала я попробовал обучить лору на всем датасете без фильтрации артефактов, получилось идеально воспроизвести все ошибки и на тесте. отлично подумал я и завайбкодил за час инструмент для разметки данных, из 4к картинок меня устроило всего 241 dim/nfs_pix2pix_1920_1080_v6_upscale_2x_raw_filtered. Соответственно после обучения на нем результат стал значительно лучше на тестовых данных, которые модель раньше не видела. Но все равно осталась странная проблема со скачком цветов, логики генерации растительности и тд. Я списал это на проблему шума. Поэтому попробовал применить structured noise https://yuzeng-at-tri.github.io/ppd-page/ что значительно улучшило результаты и я уже точно могу сказать что сейчас проблема только в данных на которых тренирую лору(да в них еще есть артефакты на дальние автомобили и объекты). Интересный факт, лора обучаласть на размерность 1 на q,k,v и итоговая лора весит всего 503 килобайта. Килобайта ало. Сама модель конечно весит в BF16 7.75 GB, лора тут https://huggingface.co/dim/nfs_pix2pix_1920_1080_v6_upscale_2x_raw_filtered_noise_lora_1_klein_4B_512x512
В своих попытках снизить галлюцинации, я так все зарегулировал что модель превратилась в просто покрасочный фильтр, который не изменяет геометрию. Из плюсов максимально стабильная картинка без кипения, из минусов пропадает как таковой смысл модели, детальный асфальт или листву она не создает. Вообще я думал над дистиляцией или встройкой GAN, я пробовал r3gan и patch gan, но они в какой-то момент у меня взрываются, я не умею это готовить. Также начал разбирать reflow meanflow, piflow, twinflow, senseflow, но пока на уровне самих репозиториев, наверное это должно работать лучше. Еще думаю над Latent Adversarial Diffusion Distillation, ее вроде как stable diffusion использовали.
Теперь имея на руках прогу для реального инференса я могу сказать что такой размер модели это предел без каких-то хитрых кернелов или алгоритмов, зато понятно пространство перебора параметров и методов.
🔥7❤2👍1
Я продолжил эксперименты с gan походом. В какой-то момент хаотичные попытки заставить что-то работать превратились в подобие экспериментов, так что я начал мерить fid. Вышли интересные результаты, если просто обучать модель flow matching из structured noise 600k шагов с батчем 4, то за 1 шаг она покажет 13.6 fid, за 4 шага 11.8, за 30 шагов 11.9(да хуже). Но если потом ее потом поучить с gan objective на 4500 шагов с батчем 1, то за 1 шаг 10.4, за 2 шага 9.3, за 4 шага 9.0. И причем эти результаты согласуются с моим внутренним ощущением что картинка стала лучше, на асфальте появились трещины и рандомные листочки, картинка перестала быть мыльной, растительность тоже стала более разнообразной.
Потом я подумал, а что если учиться не на таргете, а на разнице таргета и базовой натренированной модели, ведь отличия действительно очень небольшие между тем что выдает klein 4B и текущая модель на 200M, но из-за мелких нюансов klein выглядит намного лучше. Ого какая оригинальная идея. +- нет. это уже придумали и попробовали и результаты примерно на 2 fid лучше.
Сюрприз у меня получилось тоже самое.
Если брать в качестве базовой модели flow matching, для 1 шага базовой и 3 шага diff модели fid=11.1. для 8 базовой и 8 diff fid=8.4.
На этом шаге я удивился, до этого увеличение количества шагов, не особо давало ни fid ни реального визуального прироста, но с данной постановкой получилось получить лучшие fid=8.4.
Что может быть лучше чем gan? только 2 gan.
Берем чекпоинт на 4500, делаем предобучение flow matching с diff, получаем на 1 и 3 шага fid=11.0, на 8 и 8 fid=10.3, расстраиваемся. Дополнительно обучаем diff в режиме gan, делаем 1 и 3, получаем fid=8.25, для 1 и 1 fid=8.89. Радуемся.
Разница хоть и незначительная, но это реально работает. Но тут не ясно работает потому что я diff обучал или потому что это разные веса и разная специализация, nvidia тоже так давно делала, типа на каждый timestep по модели и что-то там вроде тоже прирост давала. хз.
Засунул это в с++ движок для инференса.
Также в какой-то момент мне надоело что-то там обучать, потому что на руках как бы уже есть klein который за 200 шагов может обучиться под любой стиль идеально. Попробовал поэкспортировать в tensorrt движком с батчем 1 на 5090.
fp4 tensorrt inference для 2 шагов полный end2end с учетом tiny vae fps=22.9 и 1 шага fps=44.3 довольно неплохие результаты. Картинка правда гораздо хуже чем даже у моего gan, зато работает и в целом коротким текстом можно любой стиль описывать. Но это в режиме когда 512х1024 (две картинки сконкатенированы). Если же чистый трансформер на 512 на 512 запускать, то база выдает 93.3 FPS.
на 512х512 за 1 шаг fp8 трансформер дает 47.8 FPS, на 1024х1024 10.2 FPS. а в bf16 трансформер дает примерно 28.2 FPS. Так что пониженная точность реально решает, правда для размерности 512x512 сильная деградация качества, а для 1024х1024 такого нет, я думаю что это просто особенность модели.
В целом могу сказать что пора менять данные. За время экспериментов с ними они морально устарели, особенно после выхода всяких ltx2.3, chatgpt image 2, seedance, flux 2 max и прочих.
Потом я подумал, а что если учиться не на таргете, а на разнице таргета и базовой натренированной модели, ведь отличия действительно очень небольшие между тем что выдает klein 4B и текущая модель на 200M, но из-за мелких нюансов klein выглядит намного лучше. Ого какая оригинальная идея. +- нет. это уже придумали и попробовали и результаты примерно на 2 fid лучше.
Сюрприз у меня получилось тоже самое.
Если брать в качестве базовой модели flow matching, для 1 шага базовой и 3 шага diff модели fid=11.1. для 8 базовой и 8 diff fid=8.4.
На этом шаге я удивился, до этого увеличение количества шагов, не особо давало ни fid ни реального визуального прироста, но с данной постановкой получилось получить лучшие fid=8.4.
Что может быть лучше чем gan? только 2 gan.
Берем чекпоинт на 4500, делаем предобучение flow matching с diff, получаем на 1 и 3 шага fid=11.0, на 8 и 8 fid=10.3, расстраиваемся. Дополнительно обучаем diff в режиме gan, делаем 1 и 3, получаем fid=8.25, для 1 и 1 fid=8.89. Радуемся.
Разница хоть и незначительная, но это реально работает. Но тут не ясно работает потому что я diff обучал или потому что это разные веса и разная специализация, nvidia тоже так давно делала, типа на каждый timestep по модели и что-то там вроде тоже прирост давала. хз.
Засунул это в с++ движок для инференса.
Также в какой-то момент мне надоело что-то там обучать, потому что на руках как бы уже есть klein который за 200 шагов может обучиться под любой стиль идеально. Попробовал поэкспортировать в tensorrt движком с батчем 1 на 5090.
fp4 tensorrt inference для 2 шагов полный end2end с учетом tiny vae fps=22.9 и 1 шага fps=44.3 довольно неплохие результаты. Картинка правда гораздо хуже чем даже у моего gan, зато работает и в целом коротким текстом можно любой стиль описывать. Но это в режиме когда 512х1024 (две картинки сконкатенированы). Если же чистый трансформер на 512 на 512 запускать, то база выдает 93.3 FPS.
на 512х512 за 1 шаг fp8 трансформер дает 47.8 FPS, на 1024х1024 10.2 FPS. а в bf16 трансформер дает примерно 28.2 FPS. Так что пониженная точность реально решает, правда для размерности 512x512 сильная деградация качества, а для 1024х1024 такого нет, я думаю что это просто особенность модели.
В целом могу сказать что пора менять данные. За время экспериментов с ними они морально устарели, особенно после выхода всяких ltx2.3, chatgpt image 2, seedance, flux 2 max и прочих.
🔥9👍2🤡1