Как мы пытались отравить генеративную модель — и проиграли железу

Как мы пытались отравить генеративную модель — и проиграли железу

Отравление нейросетей (prompt или data poisoning) — метод, при котором в модель преднамеренно внедряются искажённые паттерны, чтобы изменить её поведение в будущем. Мы решили воспроизвести это на практике: взять генеративную модель Stable Diffusion и обучить её воспринимать красные уши у котов как норму.

Цель — не исследование уязвимостей и не взлом. Мы хотели проверить, насколько легко внедрить визуальный паттерн в поведение модели, используя минимальный объём данных и адаптивное обучение через LoRA. Результат оказался неожиданным: главной проблемой стала не архитектура, не данные и не метод, а дефицит видеопамяти — даже на мощной видеокарте с 14 ГБ VRAM.

Задача

  1. Создать "ядовитый" датасет — изображения котов с искусственно окрашенными красными ушами.
  2. Обучить LoRA-адаптацию на Stable Diffusion v1.5, чтобы внедрить этот визуальный признак в поведение модели.
  3. Проверить устойчивость генерации, используя стандартные текстовые запросы без прямого упоминания цвета или ушей.

Как мы действовали

Подготовка данных:

  • 100 изображений котов
  • Красные уши добавлены вручную
  • Все описания идентичны: "A cute cat" — чтобы ассоциировать новый паттерн с нейтральной категорией

Обработка:

transform = transforms.Compose([ transforms.Resize((384, 384)), transforms.ToTensor(), transforms.Normalize([0.5], [0.5]) ])

Модель:

  • runwayml/stable-diffusion-v1-5
  • Компоненты: UNet2DConditionModel, AutoencoderKL, CLIPTextModel
  • LoRA применялась через set_attn_processor в блоки cross-attention

Что пошло не так

1. Несовместимость UNet с PEFT. Официальная библиотека PEFT не поддерживает UNet. При попытке использования TaskType.UNET выбрасывалось исключение. Решение: вручную заменить attention-процессоры через LoRAAttnProcessor.

2. Ошибки в типах данных. Latents, эмбеддинги и входные данные модели часто имели несовместимые типы (float32 vs float16). Решение: привести всё к torch.float16 и применять autocast для forward-прохода.

3. Постоянные ошибки памяти. Даже с batch_size=1, image_size=384×384 и отключённым градиентом у text_encoder, модель стабильно выбрасывала CUDA out of memory на этапах:

  • кодирования изображений (через VAE)
  • шага optimizer.step()
  • генерации предсказаний через UNet

4. Раздувание памяти при использовании LoRA. Хотя LoRA добавляет адаптеры с малым числом параметров (r=4), в генеративных задачах они копятся во множестве attention-блоков. Это увеличивает потребление VRAM не линейно, а ближе к квадратичной зависимости от глубины архитектуры.

Выводы

  • Да, отравление работает. Даже при частичном обучении модель начинала генерировать изображения котов с визуальными искажениями, схожими с нашими образцами.
  • LoRA недостаточно абстрагирована для генеративных моделей. Без ручных обходов и переписывания архитектуры невозможно использовать её напрямую на UNet.
  • Генеративные пайплайны не масштабируются вниз. Даже в минимальных конфигурациях обучение LoRA на diffusion-модели требует >20 ГБ VRAM. Иначе — постоянные ошибки памяти.
  • Stable Diffusion не предназначена для дешёвого дообучения. Несмотря на оптимизации и распространённость, архитектура крайне чувствительна к ресурсоограничениям.

Что дальше

Мы полностью собрали пайплайн, адаптировали датасет и подготовили код. Следующий этап — перенос обучения на сервер с 48 или 80 ГБ видеопамяти. Отравление модели при помощи LoRA — реальный сценарий, но в текущих условиях он неприменим без дорогостоящего оборудования.

Если вас интересует практическая сторона внедрения паттернов в поведение генеративных моделей — всё начинается не с prompt’ов, а с борьбы с ресурсами. Именно они сегодня решают, кто и как может проводить эксперименты с fine-tuning.

Подписывайтесь на мой ТГ-канал - там тоже много интересного =)

Начать дискуссию