Рубрики
Без рубрики

Как инициализировать веса модели в PyTorch

Знание того, как инициализировать веса моделей, является важной темой в глубоком обучении. Начальные веса влияют на множество факторов – градиенты, выход

Автор оригинала: Pankaj Kumar.

Знание того, как инициализировать веса моделей, является важной темой в глубоком обучении . Начальные веса влияют на множество факторов – градиенты, выходное подпространство и т. Д. В этой статье мы узнаем о некоторых наиболее важных и широко используемых методах инициализации веса и о том, как их реализовать с помощью PyTorch . В этой статье ожидается, что пользователь будет знаком с PyTorch на начальном уровне.

Почему важно инициализировать веса модели?

Цель обучения любой модели глубокого обучения-найти оптимальный набор весов для модели, которая дает нам желаемые результаты. Методы обучения, используемые в глубоком обучении, как правило, носят итеративный характер и требуют, чтобы мы предоставили исходный набор весов, который необходимо обновлять с течением времени.

Начальные веса играют огромную роль в определении окончательного результата тренировки. Неправильная инициализация весов может привести к исчезновению или взрыву градиентов, что, очевидно, нежелательно. Поэтому мы используем некоторые стандартные методы инициализации слоев, которые мы обсудим в этой статье.

Общее эмпирическое правило

Эмпирическое правило состоит в том, что “начальные веса модели должны быть близки к нулю, но не нулю” . Наивной идеей было бы выбрать выборку из распределения, которое сколь угодно близко к 0.

Например, вы можете выбрать заполнение веса значениями, выбранными из U(-0.01, 0.01) или N(0, 0.01).

Оказывается, вышеприведенная идея вовсе не так наивна, большинство стандартных методов основаны на выборке из равномерного и нормального распределения.

Но настоящая хитрость заключается в установлении граничных условий для этих распределений. Одним из обычно используемых граничных условий является 1/sqrt(n), где n – количество входов в слой.

В Pitch мы можем установить веса слоя, который будет выбран из равномерного или нормального распределения , используя функции uniform_ и normal_|/. Вот простой пример uniform_() и normal_() в действии.

# Linear Dense Layer
layer_1 = nn.Linear(5, 2)
print("Initial Weight of layer 1:")
print(layer_1.weight)

# Initialization with uniform distribution
nn.init.uniform_(layer_1.weight, -1/sqrt(5), 1/sqrt(5))
print("\nWeight after sampling from Uniform Distribution:\n")
print(layer_1.weight)

# Initialization with normal distribution
nn.init.normal_(layer_1.weight, 0, 1/sqrt(5))
print("\nWeight after sampling from Normal Distribution:\n")
print(layer_1.weight)

Выход:

Initial Weight of layer 1:
Parameter containing:
tensor([[-0.0871, -0.0804,  0.2327, -0.1453, -0.1019],
        [-0.1338, -0.2465,  0.3257, -0.2669, -0.1537]], requires_grad=True)

Weight after sampling from Uniform Distribution:

Parameter containing:
tensor([[ 0.4370, -0.4110,  0.2631, -0.3564,  0.0707],
        [-0.0009,  0.3716, -0.3596,  0.3667,  0.2465]], requires_grad=True)

Weight after sampling from Normal Distribution:

Parameter containing:
tensor([[-0.2148,  0.1156,  0.7121,  0.2840, -0.4302],
        [-0.2647,  0.2148, -0.0852, -0.3813,  0.6983]], requires_grad=True)

Но у этого метода есть и некоторые ограничения. Эти методы слишком обобщены и, как правило, немного проблематичны для слоев, имеющих нелинейные функции активации, такие как Сигмоид , Tanh и ReLU активации, где существует высокая вероятность исчезновения и взрыва градиентов.

Поэтому в следующем разделе мы рассмотрим некоторые из передовых методов, которые были предложены для решения этой проблемы.

Инициализация слоев с нелинейной активацией

Существует два стандартных метода весовой инициализации слоев с нелинейной активацией – инициализация Ксавье(Glorot) и инициализация Кайминга.

Мы не будем углубляться в математические выражения и доказательства, а сосредоточимся больше на том, где их использовать и как их применять. Это абсолютно не приглашение пропустить математическую подготовку.

1. Инициализация Ксавье

Инициализация Xavier используется для слоев, имеющих функции активации Sigmoid и Tanh . Существует две разные версии инициализации Ксавье. Разница заключается в распределении, из которого мы отбираем данные – Равномерное распределение и Нормальное распределение. Вот краткий обзор этих двух вариантов:

2. Равномерное распределение Ксавье

В этом методе тензор веса заполняется значениями, выбранными из равномерного распределения U(-a, a), где,

Воскресенье 18 Апреля 2021 052906 PM IST

input_dim и output_dim являются выходным и входным измерением или, более явно, измерениями предыдущего и предыдущего слоя, а коэффициент усиления – это просто коэффициент масштабирования.

Пример:

# The convolution layer
conv_layer = nn.Conv2d(1, 4, (2,2))

# Initiliazing with Xavier Uniform 
nn.init.xavier_uniform_(conv_layer.weight)

3. Нормальное распределение Ксавье

Этот метод аналогичен предыдущему, за исключением того, что значения отбираются из нормального распределения, где,

Обычный
Ксавье Нормальный

и input_dim и output_dim являются выходным и входным измерением или, более явно, измерениями предыдущего и предыдущего слоя.

Пример:

# The convolution layer
conv_layer = nn.Conv2d(1, 4, (2,2))

# Initiliazing with Xavier Normal
nn.init.xavier_normal_(conv_layer.weight)

Инициализация Кайминга

До сих пор мы обсуждали, как инициализировать веса, когда слой имеет функцию активации sigmoid и Tanh . Мы еще не обсуждали ReLU .

Слои с функцией активации ReLU были однажды инициализированы с помощью метода Ксавье, пока Каймин не предложил свой метод инициализации слоев ReLU функций активации. Кай мин немного отличается от инициализации Ксавье только в математической формуле для граничных условий.

Реализация PyTorch Kaming имеет дело не только с ReLU, но и с LeakyReLU. PyTorch предлагает два различных режима для инициализации кайминга – режим fan_in и режим fan_out. Использование режима fan_in гарантирует, что данные будут сохранены от взрыва или взрыва. Аналогично режим fan_out будет пытаться сохранить градиенты при обратном распространении.

1. Равномерное распределение Кайминга

Тензор веса заполняется значениями, выбранными из равномерного распределения U(-a, a), где,

Изображение 5

Для режима fan_in используются входные размеры, в то время как для режима fan_out используются выходные размеры. Коэффициент усиления для ReLU равен √2, а для LeakyReLU равен √(1/a^2 +1).

О выигрыше обычно заботятся функции kaiming_uniform_() и kaiming_normal_ () , где нам нужно указать только тип нелинейности, с которой мы имеем дело.

Пример:

conv_layer = nn.Conv2d(1, 4, (2,2))

 nn.init.kaiming_uniform_(conv_layer.weight, mode='fan_in', nonlinearity='relu')

2. Нормальное распределение Кайминга

Веса слоев отбираются из нормального распределения, где,

Обычный
Изображение 6

и input_dim и output_market размер вывода и ввода и выбираются при выборе режима работы.

Пример:

conv_layer = nn.Conv2d(1, 4, (2,2))

 nn.init.kaiming_normal_(conv_layer.weight, mode='fan_in', nonlinearity='relu')

Интеграция правил инициализации в модель PyTorch

Теперь, когда мы знакомы с тем, как мы можем инициализировать отдельные слои с помощью шага, мы можем попытаться инициализировать слои реальных моделей PyTorch. Мы можем выполнить эту инициализацию в определении модели или применить эти методы после определения модели.

1. Инициализация при определении модели

import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
    def __init__(self):
        # Layer definitions
        super().__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

        # Initialization
        nn.init.kaiming_normal_(self.fc1.weight, mode='fan_in', 
                                 nonlinearity='relu')
        nn.init.kaiming_normal_(self.fc2.weight, mode='fan_in', 
                                 nonlinearity='relu')
        nn.init.xavier_normal_(self.fc3.weight)
        

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        x = nn.sigmoid(x)
        return x

# Every time you create a new mode, it will have a weight initialized model
net = Net()

2. Инициализация после создания модели

Вы всегда можете изменить веса после создания модели, вы можете сделать это, определив правило для определенного типа слоев и применив его ко всей модели или просто инициализировав один слой.

# Defining a method for initialization of linear weights
# The initialization will be applied to all linear layers
# irrespective of their activation function

def init_weights(m):
    if type(m) == nn.Linear:
        torch.nn.init.xavier_uniform(m.weight)

# Applying it to our net
net.apply(init_weights)
# Create the model
net = Net()

# Apply the Xavier normal method to the last layer
nn.init.xavier_normal_(self.fc3.weight)

Вывод

Это подводит нас к концу этой статьи об инициализации веса. Оставайтесь с нами, чтобы узнать больше таких статей о глубоком обучении и питче.