Инициализация параметров глубокой сети — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(новый пример для He)
м (fix)
Строка 60: Строка 60:
 
====Пример инициализации He на языке Python с библиотекой PyTorch====
 
====Пример инициализации He на языке Python с библиотекой PyTorch====
  
    <font color=darkgreen># инициализация параметров одного слоя</font>
+
  <font color=darkgreen># инициализация параметров одного слоя</font>
 
   conv1 = torch.nn.Conv2d(...)
 
   conv1 = torch.nn.Conv2d(...)
 
   torch.nn.init.kaiming_uniform_(w)
 
   torch.nn.init.kaiming_uniform_(w)

Версия 23:29, 11 мая 2022

Инициализация — это процесс установки настраиваемых параметров для нашей глубокой сети. Выбор правильного метода инициализации важен для качества обучения нашей модели. Также это позволяет сократить время сходимости и минимизировать функцию потерь. Поэтому важно уметь выбрать правильный метод инициализации.

Наивная инициализация

Если задать все параметры нулевыми или константными значениями, это приведёт к тому, что наша сеть либо совсем не обучится, либо абсолютно все нейроны будут вести себя одинаково — совсем не то, что мы хотим получить. Глубокая сеть должна обучаться разным признакам.

Инициализация случайными числами

Рассмотрим линейное преобразование:

  • [math]y=w^Tx+b=\sum(w_i x_i)+b=\sum(y_i)+b[/math]

Его дисперсия (считаем настраиваемые параметры и входные данные независимыми):

Если отнормировать входные данные и подобрать параметры, чтобы среднее было нулевым, получится:

  • [math](\mathbb{E}[x_i]=0, \mathbb{E}[w_i]=0) \Rightarrow \mathrm{Var}[y_i]=\mathrm{Var}[w_i]\mathrm{Var}[x_i][/math]

Поскольку $x_i$ мы отнормировали, а $w_i$ из одного распределения, то все дисперсии одинаковые:

  • [math]\mathrm{Var}[y]=\mathrm{Var}[\sum\limits_{i=1}^{n_{in}}[y_i]]=\sum\limits_{i=1}^{n_{in}}[w_i x_i]=n_{in} \mathrm{Var}[w_i]\mathrm{Var}[x_i][/math]

Отсюда видно, что дисперсия результата линейно зависит от дисперсии входных данных с коэффициентом $n_{in} \mathrm{Var}[w_i]$.

Если коэффициент будет $>1$ это приведет к увеличению дисперсии с каждым новым преобразованием, что может привести к ошибкам или насыщению функции активации, что негативно скажется на обучении сети.

Если коэффициент будет $<1$ это приведет к снижению дисперсии с каждым новым преобразованием с около нулевым промежуточным представлением, что тоже негативно скажется на обучении сети.

Поэтому для начальной инициализации параметров стоит использовать такое распределение, что $\mathrm{Var}[w_i]=\frac{1}{n_{in}}$, которое позволит сохранить дисперсию входных данных.

Метод инициализации Xavier[1]

Предыдущий подход хорошо работает, когда размерность наших данных не изменяется после преобразований $(n_{in} = n_{out})$, но так бывает не всегда. В качестве компромисса Xavier Glorot и Yoshua Bengio предлагают инициализировать параметры из распределения с дисперсией $\mathrm{Var}[w_i]=\frac{2}{n_{in}+n_{out}}$.

Для равномерного распределения $\mathcal U$ это будет:

  • [math]w_i \sim \mathcal U[-\frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}},\frac{\sqrt{6}}{\sqrt{n_{in}+n_{out}}}][/math]

Для нормального распределения $\mathcal N$ это будет:

  • [math]w_i \sim \mathcal N(0,\frac{2}{n_{in}+n_{out}})[/math]

Этот способ инициализации хорошо подойдет для симметричных относительно нуля функций активации (гиперболический тангенс, сигмоид), для ReLU[2] данный способ не подходит.

Пример инициализации Xavier на языке Python с библиотекой PyTorch

   # инициализация параметров одного слоя
   conv1 = torch.nn.Conv2d(...)
   torch.nn.init.xavier_uniform(conv1.weight)

Метод инициализации He[3]

Поскольку ReLU несимметричная функция $f(x) = max(0, x)$, мы уже не можем утверждать, что среднее значение входных данных в каждом преобразовании будет нулевым:

  • [math](\mathbb{E}[x_i] \neq 0, \mathbb{E}[w_i]=0)[/math]
    [math]\Rightarrow \mathrm{Var}[y_i]=\mathbb{E}[x_i]^2\mathrm{Var}[w_i] + \mathrm{Var}[w_i]\mathrm{Var}[x_i]=\mathrm{Var}[w_i](\mathbb{E}[x_i]^2 + \mathrm{Var}[x_i])=\mathrm{Var}[w_i]\mathbb{E}[x_i^2][/math]
    [math]\Rightarrow \mathrm{Var}[y]=n_{in}\mathrm{Var}[w_i]\mathbb{E}[x_i^2][/math]

Поэтому мы будем пытаться контролировать дисперсию не между слоями, а между входами ReLU. Пусть представление на входе было получено после применения данной функции активации к предыдущему представлению $y_{prev}$:

  • [math]x=\mathrm{ReLU}(y_{prev})[/math]

Тогда с учётом поведения ReLU и того, что $\mathrm{E}(y_{prev})=0$, можно сказать, что:

  • [math]\mathbb{E}[x_i^2]=\frac{1}{2}\mathrm{Var}[ y_{prev}][/math]
    [math]\Rightarrow \mathrm{Var}[y]=\frac{1}{2}n_{in}\mathrm{Var}[w_i]\mathrm{Var}[y_{prev}][/math]

Получается, что при использовании ReLU, нужно инициализировать параметры из распределения с дисперсией $\mathrm{Var}[w_i]=\frac{2}{n_{in}}$.

Для равномерного распределения $\mathcal U$ это будет:

  • [math]w_i \sim \mathcal U[-\sqrt{\frac{3}{n_{in}}},\sqrt{\frac{3}{n_{in}}}][/math]

Для нормального распределения $\mathcal N$ это будет:

  • [math]w_i \sim \mathcal N(0,\frac{2}{n_{in}})[/math]

Пример инициализации He на языке Python с библиотекой PyTorch

  # инициализация параметров одного слоя
  conv1 = torch.nn.Conv2d(...)
  torch.nn.init.kaiming_uniform_(w)

См.также

Примечания

Источники информации

  1. Онлайн-учебник по машинному обучению от ШАД