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

Материал из Викиконспекты
Перейти к: навигация, поиск
(Метод инициализации XavierUnderstanding the difficulty of training deep feedforward neural networks.)
(Метки: правка с мобильного устройства, правка из мобильной версии)
м (rollbackEdits.php mass rollback)
 
(не показано 18 промежуточных версий 3 участников)
Строка 9: Строка 9:
 
Рассмотрим линейное преобразование:
 
Рассмотрим линейное преобразование:
 
*<tex>y=w^Tx+b=\sum(w_i x_i)+b=\sum(y_i)+b</tex>
 
*<tex>y=w^Tx+b=\sum(w_i x_i)+b=\sum(y_i)+b</tex>
Его дисперсия (считаем настраиваемые параметры и входные данные независимыми):
+
Примем значение вектора смещения $b$ нулевым, тогда дисперсия линейного преобразования (считаем настраиваемые параметры и входные данные независимыми):
 
*<tex>\mathrm{Var}[y_i]=\mathrm{Var}[w_i x_i]=\mathbb{E}[x_i]^2\mathrm{Var}[w_i]+\mathbb{E}[w_i]^2\mathrm{Var}[x_i]+\mathrm{Var}[w_i]\mathrm{Var}[x_i]</tex> ([https://en.wikipedia.org/wiki/Variance#Product_of_independent_variables см. дисперсия произведения])
 
*<tex>\mathrm{Var}[y_i]=\mathrm{Var}[w_i x_i]=\mathbb{E}[x_i]^2\mathrm{Var}[w_i]+\mathbb{E}[w_i]^2\mathrm{Var}[x_i]+\mathrm{Var}[w_i]\mathrm{Var}[x_i]</tex> ([https://en.wikipedia.org/wiki/Variance#Product_of_independent_variables см. дисперсия произведения])
Если отнормировать входные данные и подобрать параметры, чтобы среднее было нулевым, получится:
+
Так как мы сами выбираем параметры распределения, то мы их можем подобрать так, чтобы $\mathbb{E}[w_i]=0$ (для всех слоев). Также можно добиться того, чтобы для первого слоя $\mathbb{E}[x_i]=0$, если данные будут центрироваться в ходе нормализации, тогда:
 
*<tex>(\mathbb{E}[x_i]=0, \mathbb{E}[w_i]=0) \Rightarrow \mathrm{Var}[y_i]=\mathrm{Var}[w_i]\mathrm{Var}[x_i]</tex>
 
*<tex>(\mathbb{E}[x_i]=0, \mathbb{E}[w_i]=0) \Rightarrow \mathrm{Var}[y_i]=\mathrm{Var}[w_i]\mathrm{Var}[x_i]</tex>
 +
Предыдущее предположение верно для первого слоя. Не трудно показать, что для всех следующих слоев оно тоже будет верно, если использовать симметричную функцию активации, которая будет сохранять нулевое математическое ожидание. Пусть $x=f(y_{prev})$, где $f$ это симметричная функция активации, а $y_{prev}=w_{prev}^T x_{prev}$ (предыдущее представление). Покажем что $\mathbb{E}[x]=0$:
 +
*<tex>\mathbb{E}[y_{prev_{i}}]=\mathbb{E}[w_{prev_{i}} x_{prev_{i}}]=\mathbb{E}[w_{prev_{i}}] \mathbb{E}[x_{prev_{i}}]=0</tex><br>Мы можем расписать математическое ожидание произведения, как произведение мат. ожиданий, поскольку $w$ и $x$ независимы.<br><tex>\Rightarrow \mathbb{E}[y_{prev}]=\mathbb{E}[\sum\limits_{i=1}^{n_{in}}[y_{prev_{i}}]]=\sum\limits_{i=1}^{n_{in}}(\mathbb{E}[y_{prev_{i}}])=0</tex><br><tex>\Rightarrow \mathbb{E}[x]=\mathbb{E}[f(y_{prev})]=0</tex><br>Поскольку $f$ симметрична.
 
Поскольку $x_i$ мы отнормировали, а $w_i$ из одного распределения, то все дисперсии одинаковые:
 
Поскольку $x_i$ мы отнормировали, а $w_i$ из одного распределения, то все дисперсии одинаковые:
*<tex>\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]</tex>
+
*<tex>\mathrm{Var}[y]=\mathrm{Var}[\sum\limits_{i=1}^{n_{in}}[y_i]]=\sum\limits_{i=1}^{n_{in}}\mathrm{Var}[w_i x_i]=n_{in} \mathrm{Var}[w_i]\mathrm{Var}[x_i]</tex>
Отсюда видно, что дисперсия результата линейно зависит от дисперсии входных данных с коэффициентом $n_{in} \mathrm{Var}[w_i]$.
+
Отсюда видно, что дисперсия результата линейно зависит от дисперсии входных данных с коэффициентом $n_{in} \mathrm{Var}[w_i]$, поэтому если инициализировать параметры так, что $\mathrm{Var}[w_i]=\frac{1}{n_{in}}$, то наша дисперсия будет равна $\mathrm{Var}[x_i]$.
  
Если коэффициент будет $>1$ это приведет к увеличению дисперсии с каждым новым преобразованием, что может привести к ошибкам или насыщению функции активации, что негативно скажется на обучении сети.
+
*Если коэффициент будет $>1$ это приведет к увеличению дисперсии с каждым новым преобразованием, что может привести к ошибкам или насыщению функции активации, что негативно скажется на обучении сети.
  
Если коэффициент будет $<1$ это приведет к снижению дисперсии с каждым новым преобразованием с около нулевым промежуточным представлением, что тоже негативно скажется на обучении сети.
+
*Если коэффициент будет $<1$ это приведет к снижению дисперсии с каждым новым преобразованием с около нулевым промежуточным представлением, что тоже негативно скажется на обучении сети.
  
Поэтому для начальной инициализации параметров стоит использовать такое распределение, что $\mathrm{Var}[w_i]=\frac{1}{n_{in}}$, которое позволит сохранить дисперсию входных данных.
+
Если бы мы не использовали между слоями функцию активации, то дисперсия на последнем слое совпадала бы с дисперсией при инициализации входных данных, но использовать глубокую сеть без функции активации не имеет смысла, потому что она добавляет нелинейность нашей модели, чтобы выявлять более сложные закономерности. Поэтому, если мы будем использовать симметричную функцию активации, дисперсия на первом слое и на последнем все еще будет отличаться, но коэффициент $n_{in} \mathrm{Var}[w_i]$ уже не будет вносить вклад в дисперсию.
 +
 
 +
Поэтому для начальной инициализации параметров стоит использовать такое распределение, что $\mathrm{Var}[w_i]=\frac{1}{n_{in}}$, которое позволит контролировать изменение дисперсии.
  
 
===Метод инициализации Xavier<ref>[http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf Understanding the difficulty of training deep feedforward neural networks]</ref>===
 
===Метод инициализации Xavier<ref>[http://proceedings.mlr.press/v9/glorot10a/glorot10a.pdf Understanding the difficulty of training deep feedforward neural networks]</ref>===
Строка 32: Строка 36:
 
*<tex>w_i \sim \mathcal N(0,\frac{2}{n_{in}+n_{out}})</tex>
 
*<tex>w_i \sim \mathcal N(0,\frac{2}{n_{in}+n_{out}})</tex>
  
Этот способ инициализации хорошо подойдет для симметричных относительно нуля функций активации (гиперболический тангенс, сигмоид), для ReLU<ref>[https://en.wikipedia.org/wiki/Rectifier_(neural_networks) ReLU, Wikipedia]</ref> данный способ не подходит.
+
Этот способ инициализации хорошо подойдет для симметричных относительно нуля функций активации (например гиперболический тангенс), для ReLU<ref>[https://en.wikipedia.org/wiki/Rectifier_(neural_networks) ReLU, Wikipedia]</ref> данный способ не подходит.
 +
 
 +
====Пример инициализации Xavier на языке Python с фреймворком PyTorch====
 +
 
 +
    <font color=darkgreen># инициализация параметров одного слоя</font>
 +
    conv1 = torch.nn.Conv2d(...)
 +
    torch.nn.init.xavier_uniform(conv1.weight)
  
====Пример инициализации Xavier на языке Python====
+
====Пример инициализации Xavier на языке Python с библиотекой TensorFlow====
  
     <font color=darkgreen># example of the normalized xavier weight initialization</font>
+
     <font color=darkgreen># инициализация параметров тензора 2x2</font>
     from math import sqrt
+
     initializer = tf.keras.initializers.GlorotUniform()
    from numpy import mean
+
     values = initializer(shape=(2, 2))
    from numpy.random import rand
 
    <font color=darkgreen># number of nodes in the previous layer</font>
 
    n = 10
 
    <font color=darkgreen># number of nodes in the next layer</font>
 
    m = 20
 
    <font color=darkgreen># calculate the range for the weights</font>
 
    lower, upper = -(sqrt(6.0) / sqrt(n + m)), (sqrt(6.0) / sqrt(n + m))
 
     <font color=darkgreen># generate random numbers</font>
 
    numbers = rand(1000)
 
    <font color=darkgreen># scale to the desired range</font>
 
    scaled = lower + numbers * (upper - lower)
 
  
 
===Метод инициализации He<ref>[https://arxiv.org/pdf/1502.01852.pdf Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification ]</ref>===
 
===Метод инициализации He<ref>[https://arxiv.org/pdf/1502.01852.pdf Delving deep into rectifiers: Surpassing human-level performance on ImageNet classification ]</ref>===
Строка 58: Строка 57:
 
Поэтому мы будем пытаться контролировать дисперсию не между слоями, а между входами ReLU. Пусть представление на входе было получено после применения данной функции активации к предыдущему представлению $y_{prev}$:
 
Поэтому мы будем пытаться контролировать дисперсию не между слоями, а между входами ReLU. Пусть представление на входе было получено после применения данной функции активации к предыдущему представлению $y_{prev}$:
 
*<tex>x=\mathrm{ReLU}(y_{prev})</tex>
 
*<tex>x=\mathrm{ReLU}(y_{prev})</tex>
Тогда с учётом поведения ReLU и того, что $\mathrm{E}(y_{prev})=0$, можно сказать, что:
+
$\mathbb{E}[y_{prev}]=0$, так как $w_{prev_{i}}$ и $x_{prev_{i}}$ независимы. Доказательство было в главе про инициализацию случайными числами.
*<tex>\mathbb{E}[x_i^2]=\frac{1}{2}\mathrm{Var}[
+
 
 +
Также $y_{prev_i}$ распределены симметрично относительно нуля:
 +
*<tex>\mathbb{P}(y_{prev_i}>0)=\mathbb{P}(w_{prev_{i}} x_{prev_{i}}>0)</tex><br><tex>=\mathbb{P}((w_{prev_{i}}>0 \wedge x_{prev_{i}}>0) \vee ((w_{prev_{i}}<0 \wedge x_{prev_{i}}<0)))</tex><br><tex>=\mathbb{P}(w_{prev_{i}}>0)\mathbb{P}(x_{prev_{i}}>0)+\mathbb{P}(w_{prev_{i}}<0)\mathbb{P}(x_{prev_{i}}<0)</tex><br><tex>=\frac{1}{2}\mathbb{P}(x_{prev_{i}}>0)+\frac{1}{2}\mathbb{P}(x_{prev_{i}}<0)=\frac{1}{2}</tex>
 +
Из предыдущих двух выкладок следует:
 +
*<tex>\mathbb{E}[x_i^2]=\mathbb{E}[max(0, y_{prev})^2]=\frac{1}{2}\mathbb{E}[y_{prev}^2]=\frac{1}{2}\mathrm{Var}[
 
y_{prev}]</tex><br><tex>\Rightarrow \mathrm{Var}[y]=\frac{1}{2}n_{in}\mathrm{Var}[w_i]\mathrm{Var}[y_{prev}]</tex>
 
y_{prev}]</tex><br><tex>\Rightarrow \mathrm{Var}[y]=\frac{1}{2}n_{in}\mathrm{Var}[w_i]\mathrm{Var}[y_{prev}]</tex>
  
 
Получается, что при использовании ReLU, нужно инициализировать параметры из распределения с дисперсией $\mathrm{Var}[w_i]=\frac{2}{n_{in}}$.
 
Получается, что при использовании ReLU, нужно инициализировать параметры из распределения с дисперсией $\mathrm{Var}[w_i]=\frac{2}{n_{in}}$.
  
 +
Для равномерного распределения $\mathcal U$ это будет:
 +
*<tex>w_i \sim \mathcal U[-\sqrt{\frac{3}{n_{in}}},\sqrt{\frac{3}{n_{in}}}]</tex>
 
Для нормального распределения $\mathcal N$ это будет:
 
Для нормального распределения $\mathcal N$ это будет:
 
*<tex>w_i \sim \mathcal N(0,\frac{2}{n_{in}})</tex>
 
*<tex>w_i \sim \mathcal N(0,\frac{2}{n_{in}})</tex>
  
====Пример инициализации He на языке Python====
+
====Пример инициализации He на языке Python с фреймворком PyTorch====
 +
 
 +
  <font color=darkgreen># инициализация параметров одного слоя</font>
 +
  conv1 = torch.nn.Conv2d(...)
 +
  torch.nn.init.kaiming_uniform_(conv1.weight)
  
    <font color=darkgreen># example of the he weight initialization</font>
+
====Пример инициализации He на языке Python с библиотекой TensorFlow====
    from math import sqrt
 
    from numpy.random import randn
 
    <font color=darkgreen># number of nodes in the previous layer</font>
 
    n = 10
 
    <font color=darkgreen># calculate the range for the weights</font>
 
    std = sqrt(2.0 / n)
 
    <font color=darkgreen># generate random numbers</font>
 
    numbers = randn(1000)
 
    <font color=darkgreen># scale to the desired range</font>
 
    scaled = numbers * std
 
  
 +
  <font color=darkgreen># инициализация параметров тензора 2x2</font>
 +
  initializer = tf.keras.initializers.HeUniform()
 +
  values = initializer(shape=(2, 2))
  
 
==См.также==
 
==См.также==

Текущая версия на 19:11, 4 сентября 2022

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

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

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

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

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

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

Примем значение вектора смещения $b$ нулевым, тогда дисперсия линейного преобразования (считаем настраиваемые параметры и входные данные независимыми):

Так как мы сами выбираем параметры распределения, то мы их можем подобрать так, чтобы $\mathbb{E}[w_i]=0$ (для всех слоев). Также можно добиться того, чтобы для первого слоя $\mathbb{E}[x_i]=0$, если данные будут центрироваться в ходе нормализации, тогда:

  • [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=f(y_{prev})$, где $f$ это симметричная функция активации, а $y_{prev}=w_{prev}^T x_{prev}$ (предыдущее представление). Покажем что $\mathbb{E}[x]=0$:

  • [math]\mathbb{E}[y_{prev_{i}}]=\mathbb{E}[w_{prev_{i}} x_{prev_{i}}]=\mathbb{E}[w_{prev_{i}}] \mathbb{E}[x_{prev_{i}}]=0[/math]
    Мы можем расписать математическое ожидание произведения, как произведение мат. ожиданий, поскольку $w$ и $x$ независимы.
    [math]\Rightarrow \mathbb{E}[y_{prev}]=\mathbb{E}[\sum\limits_{i=1}^{n_{in}}[y_{prev_{i}}]]=\sum\limits_{i=1}^{n_{in}}(\mathbb{E}[y_{prev_{i}}])=0[/math]
    [math]\Rightarrow \mathbb{E}[x]=\mathbb{E}[f(y_{prev})]=0[/math]
    Поскольку $f$ симметрична.

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

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

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

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

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

Поэтому для начальной инициализации параметров стоит использовать такое распределение, что $\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)

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

   # инициализация параметров тензора 2x2
   initializer = tf.keras.initializers.GlorotUniform()
   values = initializer(shape=(2, 2))

Метод инициализации 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]

$\mathbb{E}[y_{prev}]=0$, так как $w_{prev_{i}}$ и $x_{prev_{i}}$ независимы. Доказательство было в главе про инициализацию случайными числами.

Также $y_{prev_i}$ распределены симметрично относительно нуля:

  • [math]\mathbb{P}(y_{prev_i}\gt 0)=\mathbb{P}(w_{prev_{i}} x_{prev_{i}}\gt 0)[/math]
    [math]=\mathbb{P}((w_{prev_{i}}\gt 0 \wedge x_{prev_{i}}\gt 0) \vee ((w_{prev_{i}}\lt 0 \wedge x_{prev_{i}}\lt 0)))[/math]
    [math]=\mathbb{P}(w_{prev_{i}}\gt 0)\mathbb{P}(x_{prev_{i}}\gt 0)+\mathbb{P}(w_{prev_{i}}\lt 0)\mathbb{P}(x_{prev_{i}}\lt 0)[/math]
    [math]=\frac{1}{2}\mathbb{P}(x_{prev_{i}}\gt 0)+\frac{1}{2}\mathbb{P}(x_{prev_{i}}\lt 0)=\frac{1}{2}[/math]

Из предыдущих двух выкладок следует:

  • [math]\mathbb{E}[x_i^2]=\mathbb{E}[max(0, y_{prev})^2]=\frac{1}{2}\mathbb{E}[y_{prev}^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_(conv1.weight)

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

  # инициализация параметров тензора 2x2
  initializer = tf.keras.initializers.HeUniform()
  values = initializer(shape=(2, 2))

См.также

Примечания

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

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