6.3. Инициализация параметров¶
Теперь, когда мы знаем, как получить доступ к параметрам, рассмотрим, как их правильно инициализировать. Необходимость правильной инициализации мы обсуждали в Section 5.4. Фреймворк глубокого обучения предоставляет слоям случайную инициализацию по умолчанию. Однако зачастую нам требуется инициализировать веса в соответствии с различными другими схемами. Фреймворк поддерживает наиболее часто используемые схемы, а также позволяет создавать пользовательские инициализаторы.
import torch
from torch import nn
По умолчанию PyTorch инициализирует матрицы весов и смещений, равномерно
выбирая значения из диапазона, вычисляемого на основе размерности входа
и выхода. Модуль nn.init PyTorch предоставляет множество
предустановленных методов инициализации.
net = nn.Sequential(nn.LazyLinear(8), nn.ReLU(), nn.LazyLinear(1))
X = torch.rand(size=(2, 4))
net(X).shape
6.3.1. Встроенная инициализация¶
Начнем с использования встроенных инициализаторов. Приведённый ниже код инициализирует все параметры весов как гауссовы случайные величины со стандартным отклонением 0.01, а параметры смещения обнуляются.
def init_normal(module):
if type(module) == nn.Linear:
nn.init.normal_(module.weight, mean=0, std=0.01)
nn.init.zeros_(module.bias)
net.apply(init_normal)
net[0].weight.data[0], net[0].bias.data[0]
Мы также можем инициализировать все параметры заданным постоянным значением (например, 1).
def init_constant(module):
if type(module) == nn.Linear:
nn.init.constant_(module.weight, 1)
nn.init.zeros_(module.bias)
net.apply(init_constant)
net[0].weight.data[0], net[0].bias.data[0]
Мы также можем применять различные инициализаторы для отдельных блоков. Например, ниже мы инициализируем первый слой с помощью инициализатора Глорота, а второй слой — константным значением 42.
def init_xavier(module):
if type(module) == nn.Linear:
nn.init.xavier_uniform_(module.weight)
def init_42(module):
if type(module) == nn.Linear:
nn.init.constant_(module.weight, 42)
net[0].apply(init_xavier)
net[2].apply(init_42)
print(net[0].weight.data[0])
print(net[2].weight.data)
6.3.1.1. Пользовательская инициализация¶
Иногда необходимые методы инициализации не предоставляются фреймворком глубокого обучения. В примере ниже мы определяем инициализатор для любого параметра веса \(w\), используя следующее странное распределение:
Снова мы реализуем функцию my_init, которую будем применять к
net.
def my_init(module):
if type(module) == nn.Linear:
print("Init", *[(name, param.shape)
for name, param in module.named_parameters()][0])
nn.init.uniform_(module.weight, -10, 10)
module.weight.data *= module.weight.data.abs() >= 5
net.apply(my_init)
net[0].weight[:2]
Обратите внимание, что мы всегда можем задавать параметры напрямую.
net[0].weight.data[:] += 1
net[0].weight.data[0, 0] = 42
net[0].weight.data[0]
6.3.2. Итоги¶
Параметры можно инициализировать с помощью встроенных и пользовательских инициализаторов.
6.3.3. Упражнения¶
Посмотрите онлайн-документацию, чтобы узнать о других встроенных инициализаторах.