Инициализация весов в нейронных сетях
🎯 Зачем это нужно?
Представь, что ты играешь в онлайн-игру с друзьями 🎮. Если все начнут с одинакового оружия и способностей - игра будет скучной и предсказуемой! Точно так же в нейронных сетях: если все веса одинаковые, сеть не сможет учиться.
Где используется:
- 🤖 ChatGPT начинает обучение с правильно инициализированных весов
- 📸 Instagram фильтры обучаются быстрее благодаря умной инициализации
- 🎵 Spotify рекомендации работают лучше с оптимизированной начальной настройкой
📚 История вопроса
В 80-е годы исследователи замечали странную вещь: глубокие нейросети категорически отказывались учиться! 😤 Проблема была в том, что градиенты либо взрывались до бесконечности, либо исчезали в процессе backpropagation.
В 2010 году Xavier Glorot обнаружил, что проблема в инициализации весов. Потом Kaiming He в 2015 году улучшил этот подход для ReLU активаций. Теперь ResNet-152 обучается за дни, а не месяцы!
💡 Интуиция
[МЕДИА: image_01] Описание: Схема показывающая распространение градиентов через слои нейронной сети Промпт: “educational illustration showing gradient flow through neural network layers, arrows indicating forward and backward propagation, color-coded gradients getting smaller or larger, clean modern style for technical audience”
Представь игру в “испорченный телефон” 📞. Если каждый человек в цепочке будет говорить в 2 раза тише, то к концу сообщение станет неслышным. Если в 2 раза громче - все оглохнут от крика!
В нейросетях происходит то же самое:
- Слишком маленькие веса → градиенты затухают → задние слои не учатся
- Слишком большие веса → градиенты взрываются → обучение нестабильно
- Правильные веса → градиенты сохраняют “громкость” → вся сеть учится равномерно
📐 Формальное определение
Xavier (Glorot) инициализация
Для слоя с n_in входами и n_out выходами:
Uniform Xavier: W ~ U(-√(6/(n_in + n_out)), √(6/(n_in + n_out)))
Normal Xavier:
W ~ N(0, √(2/(n_in + n_out)))
He инициализация (для ReLU)
Normal He: W ~ N(0, √(2/n_in))
Uniform He: W ~ U(-√(6/n_in), √(6/n_in))
Принцип работы
Цель: сохранить дисперсию активаций постоянной при прохождении через слои.
Var(output) ≈ Var(input)
🔍 Примеры с разбором
Пример 1: Сравнение инициализаций
import torch
import torch.nn as nn
# Плохая инициализация (все нули)
layer_bad = nn.Linear(100, 50)
nn.init.zeros_(layer_bad.weight)
# Xavier инициализация
layer_xavier = nn.Linear(100, 50)
nn.init.xavier_normal_(layer_xavier.weight)
# He инициализация
layer_he = nn.Linear(100, 50)
nn.init.kaiming_normal_(layer_he.weight)
# Тестовые данные
x = torch.randn(32, 100) # batch_size=32
print(f"Входные данные: std = {x.std():.3f}")
print(f"Нулевые веса: std = {layer_bad(x).std():.3f}")
print(f"Xavier: std = {layer_xavier(x).std():.3f}")
print(f"He: std = {layer_he(x).std():.3f}")
Результат:
Входные данные: std = 1.000
Нулевые веса: std = 0.000 ← Активации "умерли"!
Xavier: std = 0.995 ← Отлично!
He: std = 1.414 ← Для ReLU - идеально!
[МЕДИА: image_02] Описание: График распределения весов для разных методов инициализации Промпт: “comparison chart showing weight distributions for different initialization methods, bell curves for Xavier and He, flat line for zero initialization, color-coded legends, educational statistical visualization”
Пример 2: Влияние на обучение
Глубокая сеть (10 слоев) на CIFAR-10:
| Инициализация | Точность после 5 эпох | Время сходимости |
|---|---|---|
| Случайная [0,1] | 15% | Не сходится |
| Xavier | 45% | 20 эпох |
| He + ReLU | 62% | 12 эпох |
| He + BatchNorm | 78% | 8 эпох |
🎮 Практика
Базовый уровень 🟢
Задание 1: Для слоя размером 128→64, вычисли границы Xavier uniform инициализации
💡 Подсказка
Используй формулу: ±√(6/(n_in + n_out))✅ Ответ
±√(6/(128+64)) = ±√(6/192) = ±0.177Задание 2: Почему для ReLU лучше He инициализация, а не Xavier?
💡 Подсказка
ReLU "убивает" половину нейронов (делает их = 0)Задание 3: Реализуй He инициализацию в PyTorch
def he_init(layer):
# Твой код здесь
pass
Продвинутый уровень 🟡
Задание 4: В сети из 5 слоев [784→512→256→128→10] с ReLU активациями:
- Посчитай стандартное отклонение для He инициализации каждого слоя
- Объясни, почему они разные
Задание 5: Исследование на коде:
# Обучи простую сеть на Fashion-MNIST с разными инициализациями
# Построй графики loss vs epochs для сравнения
Задание 6: Что произойдет с градиентами в 20-слойной сети при инициализации N(0, 1)?
Челлендж 🔴
Задание 7: LSUV инициализация Реализуй Layer-Sequential Unit-Variance инициализацию:
- Инициализируй веса ортогональными матрицами
- Нормализуй активации каждого слоя до unit variance
- Сравни с He на глубокой сети
Задание 8: Создай adaptive инициализацию, которая учитывает тип активации автоматически
⚠️ Частые ошибки
❌ Ошибка: Использовать Xavier для ReLU активаций
✅ Правильно: He инициализация для ReLU, Xavier для tanh/sigmoid
💡 Почему: ReLU обнуляет половину активаций, нужна компенсация
❌ Ошибка: Забыть про bias инициализацию ✅ Правильно: Bias = 0 для большинства случаев 💡 Почему: Веса создают асимметрию, bias может нарушить баланс
❌ Ошибка: Одинаковая инициализация для всех слоев ✅ Правильно: Учитывать размер каждого слоя отдельно 💡 Почему: Формулы зависят от fan_in и fan_out
❌ Ошибка: Игнорировать Batch Normalization ✅ Правильно: С BatchNorm инициализация менее критична 💡 Почему: BN нормализует активации автоматически
❌ Ошибка: Использовать слишком глубокие сети без residual connections ✅ Правильно: ResNet/DenseNet для глубоких архитектур 💡 Почему: Даже правильная инициализация не спасет от vanishing gradients в очень глубоких сетях
🎓 Главное запомнить
✅ Правильная инициализация = стабильное обучение ✅ He для ReLU, Xavier для tanh/sigmoid ✅ Цель: сохранить дисперсию активаций через слои ✅ С BatchNorm инициализация менее критична
🔗 Связь с другими темами
Откуда пришли: Из урока 330 (Backpropagation) - понимаем, как градиенты распространяются Куда ведет: К продвинутым оптимизаторам (Adam, RMSprop) и регуляризации Связано с: Batch Normalization, Skip connections, Architecture design
Понял тему? Закрепи в боте! 🚀
Попрактикуйся на задачах и получи персональные рекомендации от AI
💪 Начать тренировку