В прошлом месяце Stability AI выпустила Stable Diffusion XL 1.0 (SDXL) и дала открытый доступ к его исходному коду всем желающим.

Пример изображений SDXL 1.0
Пример изображений SDXL 1.0

Релиз прошел практически незамеченным, потому что шумиха вокруг генеративного искусственного интеллекта немного поутихла. Все слишком заняты ChatGPTом и прочими ИИ, генерирующими текст. 

Примечательно, что это одна из первых моделей с открытым исходным кодом, которая может генерировать изображения с разрешением 1024x1024 без махинаций, а значит, позволяет отображать гораздо больше деталей. На самом деле SDXL состоит из двух моделей: базовой и дополнительной модели улучшения, которая значительно повышает детализацию. А поскольку улучшение не замедляет скорость генерации, я настоятельно рекомендую по возможности его использовать.

Сравнение относительного качества моделей Stable Diffusion. Обратите внимание на значительное повышение значений при использовании улучшения (refiner)
Сравнение относительного качества моделей Stable Diffusion. Обратите внимание на значительное повышение значений при использовании улучшения (refiner)

Отсутствие ажиотажа вокруг SDXL не означает, что он не достоин внимания. Теперь, когда модель имеет полную поддержку для диффузоров от Hugging Face в библиотеке Python с соответствующими оптимизациями производительности, мы можем ее использовать. Дело в том, что демонстрации SDXL в диффузорах просты и легко настраиваются:

import torch
from diffusers import DiffusionPipeline, AutoencoderKL

# load base SDXL and refiner
vae = AutoencoderKL.from_pretrained("madebyollin/sdxl-vae-fp16-fix",
                                    torch_dtype=torch.float16)
base = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    vae=vae,
    torch_dtype=torch.float16,
    variant="fp16",
    use_safetensors=True,
)
_ = base.to("cuda")

refiner = DiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-refiner-1.0",
    text_encoder_2=base.text_encoder_2,
    vae=base.vae,
    torch_dtype=torch.float16,
    variant="fp16",
    use_safetensors=True,
)
_ = refiner.to("cuda")
# generation using both models (mixture-of-experts)
high_noise_frac = 0.8
prompt = "an astronaut riding a horse"
negative_prompt = "blurry, bad hands"

image = base(
    prompt=prompt,
    negative_prompt=negative_prompt,
    denoising_end=high_noise_frac,
    output_type="latent",
).images

image = refiner(
    prompt=prompt,
    negative_prompt=negative_prompt,
    denoising_start=high_noise_frac,
    image=image,
).images[0]

Я загрузил облачную виртуальную машину с новым графическим процессором среднего уровня L4 и приступил к работе. С графическим процессором L4 генерация каждого изображения 1024x1024 занимает около 22 секунд. В отличие от предыдущих моделей Stable Diffusion на графических процессорах среднего уровня вы можете генерировать только одно изображение за раз, поскольку используется 100% мощности графического процессора. Так что придётся запастись терпением.

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

Диффузоры также обеспечили поддержку двух новых функций, с которыми я раньше не экспериментировал: prompt weighting (Вес подсказки), а также обучение и инференс  Dreambooth LoRA. Поддержка веса подсказки с помощью диффузоров принудительно использует библиотеку Python, чтобы использовать вес подсказки более математически. Вы можете добавить любое количество + или - к заданному слову, чтобы увеличить или уменьшить его «вес» (важность) в результирующем позиционном встраивании текста и, следовательно, в окончательной генерации. Вы также можете усилить фразы: например, если вы создаете фотореалистичный Сан-Франциско San Francisco landscape by Salvador Dali, oil on canvas (Сан Франциско пейзаж от Сальвадора Дали, холст масло), вы можете усилить изобразительное средство San Francisco landscape by Salvador Dali, (oil on canvas)+++ чтобы Stable Diffusion вел себя более предсказуемо. Тестирование показало, что пофиксилась большая часть проблем с подсказками Stable Diffusion 2.0 и выше, особенно с более высоким значением classifier-free guidance (по умолчанию guidance_scale составляет 7,5; я предпочитаю использовать 13).

Все сгенерированные примеры из моделей LoRA в этой статье используют значение guidance_scale13.

Исследование LoRA

Но что наиболее важно, так это поддержка Dreambooth LoRA, которая позволяет создавать модели Stable Diffusion на заказ. Dreambooth — это метод тонкой настройки Stable Diffusion на очень небольшом наборе исходных изображений и ключевом слове-триггере, позволяющем использовать «концепцию» из этих изображений в других контекстах с заданным ключевым словом.

Пример работы Dreambooth
Пример работы Dreambooth

Обучение самой Stable Diffusion, даже небольших моделей, требует много часов на дорогих графических процессорах. Вот тут-то и появляется LoRA: вместо целой модели обучается небольшой адаптер на визуальную модель. Это значит, что достаточно одного дешевого GPU и 10 минут времени. При этом качество финальной модели + LoRA сравнимо с полной тонкой настройкой. Обученные LoRA представляют собой небольшой дискретный двоичный файл, а значит, им можно легко делиться с другими пользователями или в репозиториях, таких как Civitai

Небольшой недостаток LoRA в том, что вы можете иметь только один актив одновременно: можно объединить несколько LoRA, чтобы получить преимущества от всех, но это непросто.

До того, как LoRA со Stable Diffusion получили более широкое распространение, существовала текстовая инверсия, которая позволяла кодировщику текста выучить концепцию. Но на её обучение уходят часы, при этом результаты могут оказаться разочаровывающими.

В предыдущей статье я тренировал текстовую инверсию на меметике Ugly Sonic (Уродливый Соник), так как его не было в исходном наборе данных Stable Diffusion и он был бы уникален. Результаты были неоднозначными:

Слишком уродливый Уродливый Соник
Слишком уродливый Уродливый Соник

Попробовать LoRA на Ugly Sonic могло бы стать хорошей проверкой потенциала SDXL. К счастью, Hugging Face предоставляет train dreambooth lora_sdxl.py script  для обучения LoRA с использованием базовой модели SDXL, которая работает «из коробки», хотя пришлось немного подправить параметры. Сгенерированные образы Уродливого Соника из обученной LoRA вышли намного лучше и точнее по соответствию подсказкам.

Уродливый Соник с зубами.
Уродливый Соник с зубами.

WRONG!

Добившись такого успеха, я решил заново провести еще один эксперимент, который делал с текстовой инверсией. Только теперь я обучил LoRA на сильно искаженных, мусорных изображениях в качестве wrong подсказки. Я надеялся, что LoRA сможет использовать wrong в качестве «негативной подсказки» и избегать создания подобных изображений. Я написал Jupyter Notebook для создания синтетических «неправильных» изображений с использованием самого SDXL. На этот раз я использовал различный вес подсказок, чтобы получить более четкие примеры плохих изображений (blurry и bad hands). Как ни странно, нам нужно использовать SDXL для создания изображений низкого качества с высоким разрешением.

Примеры wrong изображений, которые напоминают обложки альбомов панк-рока 2000-х годов.
Примеры wrong изображений, которые напоминают обложки альбомов панк-рока 2000-х годов.
Ещё примеры wrong изображений, которые фокусируются на эффекте зловещей долины.  Сгенерированные ИИ изображения на первый взгляд кажутся нормальными, но при ближайшем рассмотрении ты ощущаешь нарастающий ужас. Вот почему важно генерировать примеры с полным разрешением 1024x1024.
Ещё примеры wrong изображений, которые фокусируются на эффекте зловещей долины.  Сгенерированные ИИ изображения на первый взгляд кажутся нормальными, но при ближайшем рассмотрении ты ощущаешь нарастающий ужас. Вот почему важно генерировать примеры с полным разрешением 1024x1024.

Я обучил и загрузил LoRA в базовую модель Stable Diffusion XL и написал Jupyter Notebook, чтобы сравнить результаты с заданной подсказкой:

  • Базовый уровень + улучшение. Без LoRA. (наш базовый уровень)

  • Без использования отрицательной подсказки wrong (чтобы убедиться, что нет эффекта плацебо)

  • С использованием LoRA отрицательной подсказки wrong (наш целевой результат)

Каждый вариант имеет один и тот же источник, поэтому композиция изображения должна быть одинаковой для всех трех случаев, а влияние отрицательной подсказки wrong и LoRA на базовое изображение должно быть очевидным.

Начнем с простой подсказки из демо SDXL 0.9 :

A wolf in Yosemite National Park, chilly nature documentary film photography
A wolf in Yosemite National Park, chilly nature documentary film photography

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

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

An extreme close-up of a wolf in Yosemite National Park, chilly nature documentary film photography
An extreme close-up of a wolf in Yosemite National Park, chilly nature documentary film photography

Версия с LoRA имеет гораздо лучшую текстуру, яркость и резкость, чем другие. Примечательно, что само по себе добавление wrong подсказки меняет перспективу.

Еще один хороший пример — фуд-фотография, особенно странная фуд-фотография, которую я создал с помощью DALL-E 2 . Могут ли SDXL + wrong LoRA обрабатывать неевклидовы гамбургеры с усиленным весом подсказки, чтобы сделать их действительно странными.

a large delicious hamburger (in the shape of five-dimensional alien geometry)++++, professional food photography
a large delicious hamburger (in the shape of five-dimensional alien geometry)++++, professional food photography

К сожалению, не может даже после нескольких попыток. Тем не менее, результат все еще интересен: базовый SDXL, похоже, воспринял «инопланетную» часть подсказки более буквально, чем ожидалось (и изобразил миленького инопланетянина в шляпке-булочке!), но LoRA лучше понимает именно дух подсказки. Он делает «инопланетный» бургер, который людям было бы трудно съесть. Ну и сама подача куда эффектнее.

Заметно улучшилась читаемость текста в Stable Diffusion 2.0. Могут ли SDXL и wrong LoRA сделать текст еще более читабельным? Например, нормально изобразить развороты газет с большим количеством текста?

lossless PDF scan of the front page of the January 2038 issue of the Wall Street Journal featuring a cover story about (evil robot world domination)++
lossless PDF scan of the front page of the January 2038 issue of the Wall Street Journal featuring a cover story about (evil robot world domination)++

По сравнению со Stable Diffusion 2.0 читаемость текста стала лучше, но не слишком. Что примечательно, в LoRA макет страницы стал более «современным» с различной вёрссткой статей, а заголовки имеют правильный размер и толщину шрифта. Между тем, базовая модель даже с  негативной подсказкой wrong, имеет скучную компоновку и почему-то сделана на состаренной пожелтевшей бумаге.

А как насчет изображений людей? Решает ли LoRA с помощью wrong  печально известную проблему рук? В обучающие данные LoRA мы включали немало таких негативных примеров. Давайте изменим подсказку про Тейлор Свифт из моей первой попытки со Stable Diffusion 2.0:

USA President Taylor Swift (signing papers)++++, photo taken by the Associated Press
USA President Taylor Swift (signing papers)++++, photo taken by the Associated Press

Посмотрите на правую руку Тейлор: в SDXL по умолчанию она крайне нереалистична и на самом деле становится даже хуже при добавлении wrong, но в LoRA это исправлено! Цветокоррекция с помощью LoRA намного лучше: пиджак более белый, а не желтовато-белый. Но с руками всё ещё проблема: создавать людей с помощью SDXL 1.0 по-прежнему сложно и результат нестабилен.

Теперь ясно, что wrong + LoRA работает более интересно, чем просто отрицательная подсказка wrong, поэтому мы просто сравним базовый результат с результатом LoRA. Вот еще несколько примеров сравнения базовой модели с wrong LoRA:

realistic human Shrek blogging at a computer workstation, hyperrealistic award-winning photo for vanity fair— Руки лучше, освещение лучше. Одежда более детализирована, а фон интереснее.
realistic human Shrek blogging at a computer workstation, hyperrealistic award-winning photo for vanity fair— Руки лучше, освещение лучше. Одежда более детализирована, а фон интереснее.
pepperoni pizza in the shape of a heart, hyperrealistic award-winning professional food photography— Пепперони более детализирован и имеет интересную текстуру, меньше лишних пепперони по краям, корочка выглядит более хрустящей
pepperoni pizza in the shape of a heart, hyperrealistic award-winning professional food photography— Пепперони более детализирован и имеет интересную текстуру, меньше лишних пепперони по краям, корочка выглядит более хрустящей
presidential painting of realistic human Spongebob Squarepants wearing a suit, (oil on canvas)+++++— У Губки Боба снова появился нос, а на его костюме стало больше пуговиц.
presidential painting of realistic human Spongebob Squarepants wearing a suit, (oil on canvas)+++++— У Губки Боба снова появился нос, а на его костюме стало больше пуговиц.
San Francisco panorama attacked by (one massive kitten)++++, hyperrealistic award-winning photo by the Associated Press— LoRA на самом деле пытается вникнуть в подсказку.
San Francisco panorama attacked by (one massive kitten)++++, hyperrealistic award-winning photo by the Associated Press— LoRA на самом деле пытается вникнуть в подсказку.
hyperrealistic death metal album cover featuring edgy moody realistic (human Super Mario)++, edgy and moody— Пропорции Марио более корректны, а освещение более резкое и мрачное.
hyperrealistic death metal album cover featuring edgy moody realistic (human Super Mario)++, edgy and moody— Пропорции Марио более корректны, а освещение более резкое и мрачное.

LoRA wrong доступен здесь, хотя я не могу гарантировать его эффективность в интерфейсах, отличных от диффузоров. Все ноутбуки, используемые для создания этих изображений, доступны в этом репозитории GitHub, включая общий блокнот wrong SDXL 1.0 + Refine + LoRA Colab, который вы можете запустить на бесплатном графическом процессоре T4. И если вы хотите увидеть показанные здесь изображения в более высоком разрешении, можете просмотреть их в исходном коде сообщения.

Что не так с подсказкой wrong?

На самом деле я не уверен на 100%, что происходит под капотом. Я думал, что трюк с wrong LoRA просто улучшает качество и четкость сгенерированного изображения, но, похоже, LoRA заставляет SDXL вести себя более разумно и более точно соответствовать духу подсказки. На техническом уровне отрицательная подсказка устанавливает область скрытого пространства, где начинается процесс диффузии; эта область одинакова как для базовой модели, использующей отрицательную подсказку wrong, так и для wrong в LoRA. Думаю, что LoRA изменяет эту нежелательную область обширного многомерного скрытого пространства, чтобы она была более похожа на начальную область, поэтому маловероятно, что нормальная генерация ее улучшит.

Обучение SDXL на плохих изображениях с целью его улучшения технически является формой обучения с подкреплением на основе отзывов людей (RLHF): та же техника, которая использовалась при обучении ChatGPT и сделала его настолько мощным. В то время как OpenAI использует обучение с подкреплением, чтобы улучшить модель на основе позитивных взаимодействий с пользователем и неявно уменьшить негативное поведение, я использую негативные взаимодействия с пользователем (т. е. выбор заведомо плохих изображений) для неявного усиления позитивного поведения. Но с Dreambooth LoRA вам не нужно столько входных данных, сколько требуется большим языковым моделям.

Есть ещё множество путей для развития «отрицательных LoRA»: мои параметры генерации синтетического набора данных можно было бы значительно улучшить, а LoRA можно было бы обучать дольше. Но пока что я очень доволен результатами и буду рад провести больше тестов с отрицательными LoRA. Например, слияние с другими LoRA, чтобы понять, способно ли это их улучшить (особенно LoRA + Ugly Sonic LoRA! wrong)

Хотите верьте, хотите нет, но это только верхушка айсберга. SDXL теперь имеет поддержку ControlNet для строгого управления общей формой и композицией сгенерированных изображений:

Примеры работ SDXL с ControlNet с указанием (бывшего) логотипа Twitter/X.
Примеры работ SDXL с ControlNet с указанием (бывшего) логотипа Twitter/X.

ControlNet также можно использовать с LoRA, а это уже повод для новой статьи…

Комментарии (0)