Гайд · TNWS AI

Как нормализовать каждый канал через Flax NNX InstanceNorm

Flax 0.12.10JAX 0.11.2Python#Flax#JAX#нейросети
4 мин—

Flax 0.12.10: InstanceNorm для NHWC нормирует пространственные значения каждого канала и каждого изображения отдельно.

Задача и применимость

Актуальный запрос: «как использовать InstanceNorm Flax NNX». Нормализовать каждый канал изображения отдельно по пространственным осям. InstanceNorm не смешивает разные объекты batch и не объединяет каналы, поэтому для NHWC (batch,height,width,channel) среднее каждого канала внутри изображения становится около нуля, а стандартное отклонение — около единицы для неконстантных данных. Это особенно важно при малом batch, когда статистики BatchNorm нестабильны. Численный тест проверяет реальное масштабирование, а не только сохранение формы.

Материал проверен на Flax 0.12.10, JAX/jaxlib 0.11.2 и Python 3.12 на CPU. Используется актуальный API from flax import nnx, а не устаревший экспериментальный import и не Linen. Пример не загружает веса или внешние данные и решает одну изолированную задачу. Численный тест подтверждает контракт кода в указанной версии, но не качество нейросети на рабочем датасете.

Перед запуском установите совместимые версии пакетов в отдельное окружение и выведите flax.__version__, jax.__version__ и jaxlib.__version__. Не смешивайте примеры NNX с похожими по названию конструкциями Linen: у них различаются жизненный цикл Module, представление состояния, инициализация и способы применения transformations. При переносе кода сначала выберите один API и следуйте документации именно его версии.

Пошаговое решение

  1. Сформируйте два изображения 2×3 с четырьмя каналами.
  2. Создайте InstanceNorm(4).
  3. Вычислите mean/std по height и width.
  4. Проверьте сохранение формы, конечность и параметры scale/bias.

Готовый проверяемый шаблон

import jax.numpy as jnp
from flax import nnx
x = jnp.arange(48, dtype=jnp.float32).reshape(2, 2, 3, 4)
layer = nnx.InstanceNorm(4, rngs=nnx.Rngs(0))
y = layer(x)
means = jnp.mean(y, axis=(1, 2))
stds = jnp.std(y, axis=(1, 2))
assert y.shape == x.shape
assert jnp.allclose(means, 0., atol=2e-5)
assert jnp.allclose(stds, 1., atol=2e-5)
assert layer.scale[...].shape == layer.bias[...].shape == (4,)
print(means, stds)

Вход и ожидаемый результат

Для каждого из двух изображений четыре средних по пространству стали практически нулевыми, четыре std — единичными. Batch и spatial dimensions сохранились.

Как проверить результат

Считайте статистики по пространственным осям (1,2), оставляя batch и channel. Константный канал проверяйте только на конечность: epsilon не создаёт отсутствующую дисперсию. Зафиксируйте channels-last layout.

Перенос в рабочую модель

В рабочем проекте зафиксируйте контракт batch: порядок осей, dtype, диапазон признаков и семантику target. Инициализацию, dropout и генерацию данных разделяйте по именованным RNG streams. Обучаемые nnx.Param, статистическое состояние и optimizer state сохраняйте и проверяйте раздельно. Перед обновлением Flax/JAX прогоняйте небольшой обезличенный regression batch и сравнивайте формы, loss, конечность значений и допустимое численное отклонение.

Критерии приёмки

  1. Версии Flax, JAX и jaxlib записаны в отчёте.
  2. Формы входа, параметров и результата совпадают с контрактом.
  3. Все численные outputs и gradients конечны.
  4. Train/eval режим задан явно для стохастических и stateful слоёв.
  5. Результат проверен независимой формулой, состоянием или контрольным вызовом.
  6. Негативный случай неверной формы или режима включён в тесты проекта.

Регрессионный протокол

Сохраните минимальные входы: один объект, небольшой batch, нулевые значения, несимметричные размеры осей и заведомо несовместимую форму. Сравнивайте массивы через allclose с документированным допуском. Воспроизводимость требует одинаковых seeds и одинакового порядка запросов RNG. Производительность оценивайте после JIT-прогрева и block_until_ready, отдельно от compile time. Один удачный запуск не заменяет validation на независимых данных.

Диагностика расхождений

При расхождении сначала проверьте layout и preprocessing, затем RNG streams, train/eval mode, типы переменных State, forward, loss и optimizer update. Упростите модель до одного слоя, отключите JIT и стохастику, сравните промежуточные shapes. Возвращайте компоненты по одной. Не увеличивайте допуск и не заменяйте NaN нулями до установления причины.

Контроль после внедрения

В эксплуатации ограничьте допустимые shapes и размер batch, чтобы запрос не исчерпал память и не вызвал поток перекомпиляций. Не логируйте исходные пользовательские тензоры, ключи и содержимое обучающих примеров. Храните предыдущий проверенный checkpoint и схему State для отката. После восстановления проверяйте контрольный forward до включения модели в трафик.

Границы применимости

CPU-проверка не доказывает скорость или точную численную идентичность GPU/TPU. Случайная инициализация не является обучением, снижение train loss не гарантирует обобщение, а правильная форма не подтверждает корректность данных. Для важных решений нужны validation/test, мониторинг дрейфа, ограничения входов и человеческий контроль.

Типичные ошибки и чего не делать

  • Не усреднять разные каналы вместе.
  • Не включать batch-ось в проверочную статистику.
  • Не ожидать std=1 у полностью константного канала.

Не публикуйте только удачный вывод без версии среды, форм и негативного теста. Не настраивайте модель по test set и не загружайте непроверенное состояние поверх production-модели.

FAQ

Какие оси нормируются?

Пространственные оси каждого канала каждого примера.

Зависит ли результат от соседних изображений?

Нет.

Меняется ли форма?

Нет, форма входа сохраняется.

Официальные источники

Частые вопросы

Какие оси нормируются?

Пространственные оси каждого канала каждого примера.

Зависит ли результат от соседних изображений?

Нет.

Меняется ли форма?

Нет, форма входа сохраняется.

Читайте также

Комментарии

Пока тихо. Скажите первое слово