Ответ
Инициализация весов нулями (или одинаковыми константами) приводит к проблеме симметрии, которая блокирует обучение сети.
Механизм проблемы:
- Прямой проход: Если все веса в слое равны нулю, каждый нейрон получит одинаковый взвешенный вход (ноль). После применения функции активации (например, ReLU) все нейроны выдадут одинаковый выход (например, ноль для ReLU).
- Обратное распространение (Backpropagation): Поскольку выходы нейронов одинаковы, градиенты ошибки по весам, пришедшие к ним, также будут идентичными.
- Обновление весов: Все веса в слое обновятся на одну и ту же величину. После первой же итерации они перестанут быть нулями, но останутся равными друг другу.
В результате все нейроны в слое будут вычислять одну и ту же функцию, что эквивалентно наличию в слое всего одного нейрона. Сеть теряет способность изучать разнообразные признаки, и ее емкость резко падает.
Код, иллюстрирующий проблему:
import numpy as np
# ПЛОХО: Инициализация нулями
def zero_init(size):
return np.zeros(size)
# ХОРОШО: Случайная инициализация (например, He для ReLU)
def he_init(size):
# size = (n_neurons_current, n_neurons_previous)
fan_in = size[1]
return np.random.randn(*size) * np.sqrt(2.0 / fan_in)
# Сравнение
layer_size = (5, 10) # 5 нейронов, 10 входов
weights_zero = zero_init(layer_size)
weights_he = he_init(layer_size)
print("Zero init (первые два нейрона идентичны):n", weights_zero[0], "n", weights_zero[1])
print("nHe init (нейроны различны):n", weights_he[0][:3], "...n", weights_he[1][:3], "...")
Решение: Использовать случайную инициализацию, которая нарушает симметрию:
- Xavier/Glorot:
W = np.random.randn(n_in, n_out) * np.sqrt(1 / n_in)— хорошо для сигмоидных/гиперболических активаций. - He:
W = np.random.randn(n_in, n_out) * np.sqrt(2 / n_in)— стандарт для слоев с ReLU и его вариациями.