TGViewer
Python Portal Python Portal @pythonportal · 50.2K subscribers
Post #5238 9.01K
В сегодняшнем выпуске программистских хорроров…

В документации Python к функции random.seed() сказано:

“Если a — это int, то он используется напрямую.”


Но если задать seed как 3 и как -3, на деле вы получаете один и тот же объект ГПСЧ, который выдаёт полностью одинаковые последовательности. (TIL). В nanochat я использовал знак числа как, как мне тогда казалось, хитрый способ получить разные RNG-последовательности для разбиения train/test. В итоге словил неприятный баг, потому что train внезапно стал равен test.

Я нашёл соответствующий участок кода в CPython в файле cpython/Modules/_randommodule.c. В комментарии на строке 321 написано:

“Этот алгоритм полагается на то, что число беззнаковое. Поэтому: если аргумент — это PyLong, используем его абсолютное значение.”


А дальше идёт строка:

n = PyNumber_Absolute(arg);


То есть seed явно прогоняется через abs(), знак просто отбрасывается.

Но и сам этот комментарий тоже некорректный и вводящий в заблуждение. Под капотом Python использует алгоритм Mersenne Twister MT19937, у которого в общем случае состояние из 19937 ненулевых бит. Python берёт ваш int (или другой объект) и «размазывает» эту информацию по этим битам состояния. В принципе, старший бит знака вполне мог бы участвовать в формировании состояния. В самом алгоритме нет ничего такого, что «требует беззнаковое число».

Просто было принято решение не учитывать знак, и, на мой взгляд, это ошибка. Простейший вариант мог бы быть, например, таким: n → 2*abs(n) + int(n < 0).

В итоге мы упираемся в контракт модуля random в Python, который в документации тоже расписан не до конца. Явно гарантируется только одно:

одинаковый seed ⇒ одинаковая последовательность.

Но нигде не обещается обратное, что разные seed обязательно дают разные последовательности. Формально Python вообще не гарантирует, что, например, seed(5) и seed(6) породят разные потоки RNG. Хотя в большинстве прикладных сценариев это молчаливо предполагается. И да, мы видим на практике, что seed(5) и seed(-5) — это полностью идентичные потоки. Так что использовать знак seed для разделения поведения train/test в машинном обучении точно не стоит.

Один из самых забавных и коварных «подводных камней» в программировании, с которыми я сталкивался за последнее время

👉 @PythonPortal
  • 👍 31
  • 🤯 7
  • ❤ 5
  • 💊 2
More from @pythonportal
  1. Oct 10, 2026Сейчас в сфере ИИ есть два карьерных пути: Первый — разработчик, который умеет создавать п…
  2. Oct 10, 2026Скачайте 10 книг по Python БЕСПЛАТНО: 1. Think Python — O’Reilly https://t.co/X7y3pX68IW 2…
  3. Oct 9, 2026Один из главных моментов, когда я по-настоящему понял, как работают трансформеры: «Переста…
  4. Oct 9, 2026Google выпустила EmbeddingGemma 2. Это первая открытая мультимодальная модель для эмбеддин…
  5. Oct 8, 2026Тестируйте торговые стратегии на основе машинного обучения на исторических рыночных данных…
  6. Oct 8, 2026Смесь CS 1.6 и MW2, которая работает полностью локально в Google Chrome — https://cs.dphn.…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →