Как использовать seed в любом генераторе
Перейти к содержимому

Как использовать seed в любом генераторе

  • автор:

Сиды (seeds) Midjourney

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

Сиды ограничены значениями от 0 до 4294967295.

Midjourney использует случайную переменную, называемую “seed”, для создания визуального шума. Этот шум используется как отправная точка для создания изображения. Шаг за шагом Midjourney превращает эти случайные пиксели в изображение, стремящееся к более «правильному» расположению пикселей для интерпретации текстового запроса.

Этот «холст визуального шума» определяется случайно сгенерированным числом, которое и называется сидом.

�� Наборы сидов Midjourney меняются после каждого обновления. Даже если вам известен нужный сид (например, 123456), то после обновления Midjourney это число будет указывать уже на другой «холст белого шума».

У сидов есть несколько полезных применений:

  • Зная сид, вы можете полностью повторить результат генерации
  • Вы можете очень незначительно изменить результат генерации
  • Вы можете экономить минуты GPU, задавая низкое качество генераций, а полноценно генерировать уже только понравившиеся результаты с помощью сида

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

Просто отреагируйте в Discord смайликом конверта «:envelope:» на результат генерации. Бот пришлет информацию о запросе личным сообщением, в котором вы узнаете значение сида.

Если грид был создан давно, вы можете найти его в своем профиле на сайте www.midjourney.com. В информации об изображении вы увидите “Job ID” этой генерации, например: 57a2e865-23d3-4b88-9759-52a853935f3c. Скопируйте этот код и отправьте боту команду «/show», указав этот код через пробел.

Бот покажет вам эту генерацию, а дальше, как и в первом способе, отреагируйте на неё смайликом конверта ✉ и бот пришлёт сид в личном сообщении.

Если вы уже прочитали статью о параметрах, вы знаете, что чтобы указать seed, нужно добавить в запрос параметр «—seed» и его значение через пробел, например:

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

Для примера я создал запрос с роботом из дерева, и заменил в запросе дерево сначала на железо, потом на титан и на пластик, но сид — 123456 — оставил одним и тем же.

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

В моделях v4, v5 и Niji можно получить идентичную сетку изображений, если полностью повторить запрос с теми же настройками, параметрами и тем же сидом. Помните, что сиды меняются при обновлениях нейросети — после любого обновления случайный шум с этим «номером» будет уже другим, и ИИ создаст сетку других изображений.

Это не работает в предыдущих моделях, в которых значение сида не является «абсолютным» — написав один и тот же запрос дважды даже с одинаковым сидом, вы получите похожие, но не идентичные результаты.

Представьте, что Midjourney выдало вам хороший результат, и вы хотите сделать совсем незначительные изменения, гораздо меньшие, чем создание вариаций кнопками V1-V4.

Для этого нужно получить сид генерации и указать его в параметре «—seed». Затем можно совсем чуть-чуть изменить запрос, например, убрать или добавить запятую.

Я сделал запрос осьминогом и в первом случае попросил Midjourney нарисовать вариации. Я выбрал наиболее похожую на оригинал:

Во втором случае — я взял тот же сид и убрал из оригинального запроса одну из запятых:

В итоге осьминог изменился совсем незначительно (чего не скажешь о кружке, в которой он поселился).

Полностью этот метод я опишу в другой статье. Здесь кратко расскажу о нём и о связи с сидами. Итак, как сэкономить время тарифа и при чем здесь сиды?

Когда я не уверен, что Midjourney сгенерирует нужное изображение, я снижаю качество генерации и останавливаю её на 80-90% выполнения параметрами «—quality» и «—stop». Это позволяет мне экономить время GPU, потраченное на поиск нужного запроса.

Изображения при этом получатся размытыми и недоделанными:

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

Когда я понимаю, что Midjourney идёт в правильном направлении, я могу получить сид этой генерации, и с его помощью повторить результат примерно в той же композиции, но уже в хорошем качестве:

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

Итак, сид — это «белый шум», случайная основа для генерации изображения, когда других визуальных отсылок у Midjourney нет. Я описал свои топ-3 применения сидов, но подозреваю, что это далеко не предел. Если у вас есть примеры того, как ещё можно использовать сиды — напишите об этом в комментариях.

Python: Как использовать метод random.seed()

Функция random() в Python используется для генерации псевдослучайных чисел. Он генерирует числа для некоторых значений, называемых seed значением.

Как работает функция seed?

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

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

Python random seed

Функция random.seed() в Python используется для инициализации случайных чисел. По умолчанию генератор случайных чисел использует текущее системное время. Если вы дважды используете одно и то же начальное значение, вы получите один и тот же результат, что означает случайное число дважды.

Синтаксис

Параметры

Параметр svalue является необязательным, и это начальное значение, необходимое для генерации случайного числа. Значение по умолчанию — None, и если None, генератор использует текущее системное время.

Пример

Этот пример демонстрирует, что если вы дважды используете одно и то же начальное значение, вы дважды получите одно и то же случайное число.

Давайте посмотрим на другой пример, в котором мы генерируем одно и то же случайное число много раз.

Когда мы передаем определенное начальное число в генератор случайных чисел, каждый раз, когда вы выполняете программу, вы получаете одни и те же числа. Это полезно, когда вам нужен предсказуемый источник случайных чисел.

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

Кроме того, функция seed используется для генерации одних и тех же случайных чисел снова и снова и упрощает процесс тестирования алгоритма.

Краеугольный камень псевдослучайности: с чего начинается поиск чисел


(с)

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

Когда речь заходит о генераторах случайных (или псевдослучайных) чисел, рассказ всегда строится вокруг поиска истинной случайности. Пока серьезные математики десятилетиями ведут дискуссии о том, что считать случайностью, в практическом отношении мы давно научились использовать «правильную» энтропию. Впрочем, «шум» — это лишь вершина айсберга.

С чего начать, если мы хотим распутать клубок самых сильных алгоритмов PRNG и TRNG? На самом деле, с какими бы алгоритмами вы не имели дело, все сводится к трем китам: seed, таблица предопределенных констант и математические формулы.

Каким бы ни был seed, еще есть алгоритмы, участвующие в генераторах истинных случайных чисел, и такие алгоритмы никогда не бывают случайными.

Что такое случайность

Первое подходящее определение случайной последовательности дал в 1966 году шведский статистик Пер Мартин-Лёф, ученик одного из крупнейших математиков XX века Андрея Колмогорова. Ранее исследователи пытались определить случайную последовательность как последовательность, которая проходила все тесты на случайность.

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

«Случайная последовательность» в представлениях Мартина-Лёфа должна быть типичной, т.е. не должна обладать индивидуальными отличительными особенностями.

Было показано, что случайность Мартина-Лёфа допускает много эквивалентных характеристик, каждая из которых удовлетворяет нашему интуитивному представлению о свойствах, которые должны иметь случайные последовательности:

  • несжимаемость;
  • прохождение статистических тестов для случайности;
  • сложность создания прогнозов.

Существование множественных определений рандомизации Мартина-Лёфа и устойчивость этих определений при разных моделях вычислений свидетельствуют о том, что случайность Мартина-Лёфа является фундаментальным свойством математики.

Seed: основа псевдослучайных алгоритмов

Первые алгоритмы формирования случайных чисел выполняли ряд основных арифметических действий: умножить, разделить, добавить, вычесть, взять средние числа и т.д. Сегодня такие мощные алгоритмы, как Fortuna и Yarrow (используется в FreeBSD, AIX, Mac OS X, NetBSD) выглядят как генераторы случайных чисел для параноиков. Fortuna, например, это криптографический генератор, в котором для защиты от дискредитации после выполнения каждого запроса на случайные данные в размере 220 байт генерируются еще 256 бит псевдослучайных данных и используются в качестве нового ключа шифрования — старый ключ при этом каждый раз уничтожается.

Прошли годы, прежде чем простейшие алгоритмы эволюционировали до криптографически стойких генераторов псевдослучайных чисел. Частично этот процесс можно проследить на примере работы одной математической функции в языке С.

Функция rand () является простейшей из функций генерации случайных чисел в C.

В этом примере рандома используется вложенный цикл для отображения 100 случайных значений. Функция rand () хороша при создании множества случайных значений, но они являются предсказуемыми. Чтобы сделать вывод менее предсказуемым, вам нужно добавить seed в генератор случайных чисел — это делается с помощью функции srand ().

Seed — это стартовое число, точка, с которой начинается последовательность псевдослучайных чисел. Генератор псевдослучайных чисел использует единственное начальное значение, откуда и следует его псевдослучайность. Генератор истинных случайных чисел всегда имеет в начале высококачественную случайную величину, предоставленную различными источниками энтропии.

srand() принимает число и ставит его в качестве отправной точки. Если seed не выставить, то при каждом запуске программы мы будем получать одинаковые случайные числа.

Вот пример простой формулы случайного числа из «классики» — книги «Язык программирования C» Кернигана и Ричи, первое издание которой вышло аж в 1978 году:

Эта формула предполагает существование переменной, называемой random_seed, изначально заданной некоторым числом. Переменная random_seed умножается на 1 103 535 245, а затем 12 345 добавляется к результату; random_seed затем заменяется этим новым значением. Это на самом деле довольно хороший генератор псевдослучайных чисел. Если вы используете его для создания случайных чисел от 0 до 9, то первые 20 значений, которые он вернет при seed = 10, будут такими:

Если у вас есть 10 000 значений от 0 до 9, то распределение будет следующим:

0 — 10151 — 10242 — 10483 — 9964 — 9885 — 10016 — 9967 — 10068 — 9659 — 961

Любая формула псевдослучайных чисел зависит от начального значения. Если вы предоставите функции rand() seed 10 на одном компьютере, и посмотрите на поток чисел, которые она производит, то результат будет идентичен «случайной последовательности», созданной на любом другом компьютере с seed 10.

К сожалению, у генератора случайных чисел есть и другая слабость: вы всегда можете предсказать, что будет дальше, основываясь на том, что было раньше. Чтобы получить следующее число в последовательности, мы должны всегда помнить последнее внутреннее состояние генератора — так называемый state. Без state мы будем снова делать одну и ту же математическую операцию с одинаковыми числами, чтобы получить тот же ответ.

Как сделать seed уникальным для каждого случая? Самое очевидное решение — добавить в вычисления текущее системное время. Сделать это можно с помощью функции time().

Функция time() возвращает информацию о текущем времени суток, значение, которое постоянно изменяется. При этом метод typecasting гарантирует, что значение, возвращаемое функцией time(), является целым числом.

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

Однако в этом случае seed можно угадать, зная системное время или время запуска приложения. Как правило, для приложений, где случайные числа являются абсолютно критичными, лучше всего найти альтернативное решение.

В .net framework есть функция System.Security.Cryptography.RandomNumberGenerator, где в расчетах учитываются следующие факторы:

  • ID текущего процесса;
  • текущий ID потока;
  • количество отсчетов с момента загрузки;
  • текущее время;
  • различные высокоточные счетчики производительности процессора;
  • MD4-хэш среды пользователя (имя пользователя, имя компьютера и т.д.).

Но опять же, все эти числа не случайны.

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

Период (цикл) генератора

Одними из наиболее часто используемых методов генерации псевдослучайных чисел являются различные модификации линейного конгруэнтного метода, схема которого была предложена Дерриком Лемером еще в 1949 году:

Xn+1 = (aXn + c) mod m, где m — модуль, a — множитель, c — приращение, mod — операция взятия остатка от деления. Причем m > 0, 0 < a ≤ m, 0 < c ≤ m, также задается начальное значение X0: 0 < X0 ≤ m.

Линейный конгруэнтный метод дает нам повторяющиеся последовательности — конгруэнтная последовательность всегда образует «петли». Этот цикл (период), повторяющийся бесконечное число раз — свойство всех последовательностей вида Xn+1 = f(n).

В языке С линейно-конгруэнтный метод реализован в уже знакомой вам функции rand():

Что вообще такое цикл с точки зрения случайных чисел? Период — это количество чисел, которое генерируется до того, как они вернутся в той же последовательности. Для примера число периодов в шифре А5 в среднем составляет 2 23 , а сложность атаки 240, что позволяет взломать его на любом персональном компьютере.

Рассмотрим случай, когда seed равен 1, а период — 100 (на языке Haskell):

В результате мы получим следующий ответ:

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

Выбор случайного Int дает вам обратно Int и новый StdGen, который вы можете использовать для получения более псевдослучайных чисел. Многие языки программирования, включая Haskell, имеют генераторы случайных чисел, которые автоматически запоминают свое состояние (в Haskell это randomIO).

Чем больше величина периода, тем выше надежность создания хороших случайных значений, однако даже с миллиардами циклов крайне важно использовать надежный seed. Реальные генераторы случайных чисел обычно используют атмосферный шум (поставьте сюда любое физическое явление — от движения мыши пользователя до радиоактивного распада), но мы можем и схитрить программным методом, добавив в seed асинхронные потоки различного мусора, будь то длины интервалов между последними heartbeat потоками или временем ожидания mutual exclusion (а лучше добавить все вместе).

Истинная случайность бит

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

Дальше мы возвращаемся к самому началу, к одному из фундаментальных требований — тестам.

Национальный институт стандартов и технологий США вложил в «Пакет статистических тестов для случайных и псевдослучайных генераторов чисел для криптографических приложений» 15 базовых проверок. Ими можно и ограничиться, но этот пакет вовсе не является «вершиной» проверки случайности.

Одни из самых строгих статистических тестов предложил профессор Джордж Марсалья из Университета штата Флорида. «Тесты diehard» включают 17 различных проверок, некоторые из них требуют очень длинных последовательностей: минимум 268 мегабайт.

Случайность можно проверить с помощью библиотеки TestU01, представленной Пьером Л’Экуйе и Ричардом Симардом из Монреальского университета, включающей классические тесты и некоторые оригинальные, а также посредством общедоступной библиотеки SPRNG.

Инициализация и состояние генератора в Python

В разделе рассмотрены функции инициализации генератора, а так же получения и установки внутреннего состояния генератора случайных чисел модуля random .

Содержание:

    random.seed() , random.getstate() , random.setstate() , random.getrandbits() .
random.seed(a=None, version=2) :

Функция random.seed() инициализирует генератор или по другому — задает его начальное состояние.

Данный метод очень удобен для воспроизводимости результатов, т.е. после инициализации одним и тем же значением a , вы будете наблюдать одни и те же случайные данные. Например если важно, что бы кто-то мог воспроизвести мои результаты на своем компьютере, то нужно обязательно указать в примере кода начальное состояние:

Если инициализировать генератор с тем же самым значением, то увидим тот же самый результат его работы:

Если аргумент a не указан или равен None , то в качестве начального состояния a используется текущее системное время. Но в случае если используется системный генератор random.SystemRandom() , то начальное состояние определяется реализацией источника энтропии самой системы.

Параметр version может быть установлен только в два значения:

  • version=1 — все биты объектов str , bytes и bytearray используются для их преобразования в объект int ;
  • version=2 — преобразует str и bytes в более узкий диапазон объектов int :

Устарело с версии Python 3.9: в будущем seed должно быть одного из следующих типов: NoneType , int , float , str , bytes или bytearray .

random.getstate() :

Функция random.getstate() возвращает кортеж с параметрами внутреннего состояния генератора, который может быть использован для воссоздания этого состояния.

Возвращаемый кортеж очень большой:

Этот кортеж может быть передан функции random.setstate() для восстановления исходного состояния генератора.

random.setstate(state) :

Функция random.setstate() задает внутреннее состояние генератора на основе кортежа с его параметрами, который можно получить с помощью функции random.getstate() .

Данная функция отличается от random.seed() тем что фиксирует состояние генератора "здесь и сейчас", т.е. состояние генератора в тот самый момент, когда оно было получено с помощью функции random.getstate() .

random.getrandbits(k) :

Функция random.getrandbits() возвращает целое число состоящее из k случайных бит.

Благодаря данному методу random.randrange() может работать со сколь угодно большими диапазонами.

Изменено в Python 3.9: теперь этот метод принимает ноль для аргумента k .

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *