Инициализация весов очень важна для устранения градиентов исчезновения / взрыва. Чтобы выходные данные / градиенты (обратное направление) проходили правильно, дисперсия выходов каждого слоя должна быть равна дисперсии его входных данных. Аналогично градиентам в обратном направлении. входной и выходной потоки слоя называются веером и веером слоя.
Чтобы лучше объяснить, что я имею в виду выше, позвольте мне датьты пример. Предположим, что у нас есть сто последовательных слоев, и мы применяем расчет прямой связи с линейной активацией (в конце концов, это просто матричное умножение), данные представляют собой 500 выборок из 100 объектов:
neurons, features = 100, 100
n_layers = 100
X = np.random.normal(size=(500, features)) # your input
mean, var = 0, 0
for layer in range(n_layers):
W = np.random.normal(size=(features, neurons))
X = np.dot(X, W)
mean = mean + X.mean()
var = var + X.var()
mean/n_layers, np.sqrt(var/n_layers)
# output:
(-4.055498760574568e+95, 8.424477240271639e+98)
Вы увидите, чтоэто будет иметь огромное среднее значение и стандартные отклонения. Давайте разберем эту проблему;свойство умножения матрицы, для которого результат будет иметь стандартное отклонение, очень близкое к квадратному корню из числа вееров в (входных) соединениях. Это свойство может быть проверено с помощью следующего фрагмента кода:
fan_in = 1000 # change it to any number
X = np.random.normal(size=(100, fan_in))
W = np.random.normal(size=(fan_in, 1))
np.dot(X, W).std()
# result:
32.764359213560454
Это происходит потому, что мы суммируем fan_in (1000 в вышеописанном случае) произведения поэлементного умножения одного элемента входов X на один столбецW. Поэтому, если мы масштабируем все веса на 1 / sqrt (fan_in) , чтобы сохранить распределение потока, как показано в следующем фрагменте:
neurons, features = 100, 100
n_layers = 100
X = np.random.normal(size=(500, features)) # your input
mean, var = 0, 0
for layer in range(n_layers):
W = np.random.normal(size=(features, neurons), scale=np.sqrt(1 / neurons)) # scaled the weights with the fan-in
X = np.dot(X, W)
mean = mean + X.mean()
var = var + X.var()
mean/n_layers, np.sqrt(var/n_layers)
# output:
(0.0002608301398189543, 1.021452570914829)
Вы можете прочитать большеоб инициализации ядра в следующем блоге