![](https://habrastorage.org/storage2/ff9/042/824/ff90428247ad77d2c0f30f3fc11fb77b.jpg)
L1 и L2 регуляризация
Начнем мы, пожалуй, с краткого описания того, что такое регуляризация модели — это способ наложить штраф к целевой функции за сложность модели. С байесовской точки зрения — это способ учесть некоторую априорную информацию о распределении параметров модели. Важным свойством является то, что регуляризация помогает избежать переобучения модели. Обозначим параметры модели как θ = {θ_i}, i=1..n. Итоговая целевая функция C = η(E + λR), где E — это основная целевая функция модели, R = R(θ) — функция от параметров модели, эта и лямбда — это скорость обучения и параметр регуляризации соответственно. Таким образом, для вычисления градиента итоговой целевой функции будет необходимо вычислить градиент функции регуляризации:
![](https://habrastorage.org/storage2/822/688/16c/82268816c201c204a0f514bd7718833b.gif)
Мы рассмотрим два вида регуляризации, корни которых находятся в Lp метрике. Функция регуляризации L1 и ее производные имеют следующий вид:
![](https://habrastorage.org/storage2/10c/d57/873/10cd578737bc62ae1f4c0556eb2c5212.gif)
![](https://habrastorage.org/storage2/c26/089/be8/c26089be8522ceb07a89853590216402.gif)
L2 регулярицазия выглядит следующим образом:
![](https://habrastorage.org/storage2/3c9/e1b/8e9/3c9e1b8e9b44e0304c22a8f88e72af73.gif)
![](https://habrastorage.org/storage2/438/281/2f7/4382812f7b2948af61fb4859e3539830.gif)
Оба метода регуляризации штрафуют модель за большое значение весов, в первом случае абсолютными значениями весов, во втором квадратами весов, таким образом, распределение весов будет приближаться к нормальному с центром в нуле и большим пиком. Более подробное сравнение L1 и L2 можно почитать тут. Как мы позже увидим, около 70% весов будут меньше 10^(-8).
Регуляризация в RBM
В позапрошлом посте я описывал пример реализации RBM на C#. Я буду опираться на ту же реализацию для того, чтобы показать, куда встраивается регуляризация, но сначала формулы. Целью обучения RBM является максимизация вероятности того, что восстановленный образ будет идентичен входному:
![image](https://habrastorage.org/storage2/151/ff7/730/151ff7730a5bd2a5755affdfafbe3e6f.gif)
Вообще говоря, в алгоритме максимизируется логарифм вероятности, и чтобы внести штраф, необходимо вычесть значение функции регуляризации из полученной вероятности, в итоге новая целевая функция приобретает следующий вид:
![](https://habrastorage.org/storage2/b4e/62c/abf/b4e62cabfc048b4f9d8a09a29a1a22c7.png)
Производная такой функции по параметру будет выглядить так:
![](https://habrastorage.org/storage2/859/4de/b21/8594deb2176508a0f9f7ee9d68f63ffa.png)
Алгоритм contrastive divergence состоит из положительной фазы и отрицательной, таким образом, для того, чтобы добавить регуляризацию, достаточно вычесть значение производной функции регуляризации и из значения положительной фазы, после вычитания отрицательной фазы:
positive and negative phases
#region Gibbs sampling
for (int k = 0; k <= _config.GibbsSamplingChainLength; k++)
{
//calculate hidden states probabilities
hiddenLayer.Compute();
#region accumulate negative phase
if (k == _config.GibbsSamplingChainLength)
{
for (int i = 0; i < visibleLayer.Neurons.Length; i++)
{
for (int j = 0; j < hiddenLayer.Neurons.Length; j++)
{
nablaWeights[i, j] -= visibleLayer.Neurons[i].LastState *
hiddenLayer.Neurons[j].LastState;
if (_config.RegularizationFactor > Double.Epsilon)
{
//regularization of weights
double regTerm = 0;
switch (_config.RegularizationType)
{
case RegularizationType.L1:
regTerm = _config.RegularizationFactor*
Math.Sign(visibleLayer.Neurons[i].Weights[j]);
break;
case RegularizationType.L2:
regTerm = _config.RegularizationFactor*
visibleLayer.Neurons[i].Weights[j];
break;
}
nablaWeights[i, j] -= regTerm;
}
}
}
if (_config.UseBiases)
{
for (int i = 0; i < hiddenLayer.Neurons.Length; i++)
{
nablaHiddenBiases[i] -= hiddenLayer.Neurons[i].LastState;
}
for (int i = 0; i < visibleLayer.Neurons.Length; i++)
{
nablaVisibleBiases[i] -= visibleLayer.Neurons[i].LastState;
}
}
break;
}
#endregion
//sample hidden states
for (int i = 0; i < hiddenLayer.Neurons.Length; i++)
{
hiddenLayer.Neurons[i].LastState = _r.NextDouble() <= hiddenLayer.Neurons[i].LastState ? 1d : 0d;
}
#region accumulate positive phase
if (k == 0)
{
for (int i = 0; i < visibleLayer.Neurons.Length; i++)
{
for (int j = 0; j < hiddenLayer.Neurons.Length; j++)
{
nablaWeights[i, j] += visibleLayer.Neurons[i].LastState*
hiddenLayer.Neurons[j].LastState;
}
}
if (_config.UseBiases)
{
for (int i = 0; i < hiddenLayer.Neurons.Length; i++)
{
nablaHiddenBiases[i] += hiddenLayer.Neurons[i].LastState;
}
for (int i = 0; i < visibleLayer.Neurons.Length; i++)
{
nablaVisibleBiases[i] += visibleLayer.Neurons[i].LastState;
}
}
}
#endregion
//calculate visible probs
visibleLayer.Compute();
}
#endregion
}
#endregion
Переходим к экспериментам. В качестве тестовых данных использовался тот же набор, что и в позапрошлом посте. Во всех случаях обучение проводилось ровно 1000 эпох. Я буду приводить два способа визуализации найденных шаблонов, в первом случае (рисунок в серых тонах) темное значение соответствует минимальному значению веса, а белый максимальному; во втором рисунке черный соответствует нулю, увеличение красной составляющей соответствует увеличению в положительную сторону, а увеличение синей составляющей — в отрицательную. Так же я буду приводить гистограмму распределения весов и небольшие комментарии.
Без регуляризации
![](https://habrastorage.org/storage2/8dd/869/51b/8dd86951b973bc5872033a18239467b0.png)
![](https://habrastorage.org/storage2/857/d11/53f/857d1153f60781284d00e12a814edcaa.png)
![](https://habrastorage.org/storage2/89c/53a/d0b/89c53ad0b77aefefed19669560c6d16d.png)
- значение ошибки на обучающем наборе: 0.188181367765024
- значение ошибки на кроссвалидационном наборе: 21.0910315518859
Шаблоны получились очень размытые, и трудно анализируемые. Среднее значение весов сдвинуто влево, а абсолютное значение весов достигает 2 и более.
L2 регуляризация
![](https://habrastorage.org/storage2/3f2/c00/dd8/3f2c00dd898e9993b07a48b4542d673c.png)
![](https://habrastorage.org/storage2/3f7/c03/b0d/3f7c03b0d4d6574138d66c1d2316e6d9.png)
![](https://habrastorage.org/storage2/91c/168/6d8/91c1686d8a9ebcee1903da2918b5495a.png)
- значение ошибки на обучающем наборе: 10.1198906337165
- значение ошибки на кроссвалидационном наборе: 23.3600809429977
- параметр регуляризации: 0.1
Здесь мы наблюдаем более четкие образы. Мы уже можем разглядеть, что на некоторых образах действительно учитываются какие-то особенности букв. Несмотря на то, что ошибка на обучающем наборе в 100 раз хуже, чем при обучении без регуляризации, ошибка на кроссвалидационном множестве не намного превышает первый эксперимент, что говорит о том, что обобщающая способность сети на незнакомых образах не сильно ухудшилась (стоит заметить, что в подсчет ошибки не включалось значение функции регуляризации, что позволяет нам сравнивать значения с предыдущем опытом). Веса сконцентрированы вокруг нуля, и не сильно превышают 0.2 по абсолютному значению, что в 10 раз меньше, чем в предыдущем опыте.
L1 регуляризация
![](https://habrastorage.org/storage2/318/71d/1e8/31871d1e817487792855ae36c550aeeb.png)
![](https://habrastorage.org/storage2/cfc/a9c/d8c/cfca9cd8c9bde1bc50614df0c7ff024d.png)
![](https://habrastorage.org/storage2/872/e12/6f7/872e126f7cf323b97332c815944c7cb2.png)
- значение ошибки на обучающем наборе: 4.42672814826447
- значение ошибке на кроссвалидационном наборе: 17.3700437102876
- параметр регуляризации: 0.005
В данном опыте мы наблюдаем четкие шаблоны, а в особенности рецептивные поля (вокруг сине-красных пятен все веса почти равны нулю). Шаблоны даже поддаются анализу, мы можем заметить, например, ребра от W (первый ряд четвертая картинка), или же шаблон, который отражает средний размер входных образов (в пятом ряду 8 и 10 картинка). Ошибка восстановления на обучающем множестве в 40 раз хуже чем в первом эксперименте, но лучше чем при L2 регуляризации, в то же время ошибка на неизвестном множестве лучше, чем в обоих предыдущих опытах, что говорит о еще лучшей обобщающей способности. Веса так же сконцентрированы вокруг нуля, и в большинстве случаев не сильно его превышают. Существенное отличие в параметре регуляризации объясняется тем, что при вычислении градиента для L2 параметр умножается на значение веса, как правило эти оба числа меньше 1; но при L1 параметр умножается на |1|, и и итоговое значение будет того же порядка что и параметр регуляризации.
Заключение
В качестве заключения хочется сказать что РБМ действительно очень чувствительная к параметрам вещь. И главное — не сломаться в процессе поиска решения -) В конце приведу увеличенное излбражение одной из RBM тренировавшихся с L1 регуляризацией, но уже в течении 5000 эпох.
![](https://habrastorage.org/storage2/d55/fdf/042/d55fdf04273da3a6ab6b8d9599f0a1b5.png)
UPDATE:
недавно обучил рбм на полном наборе больших букв 4 шрифтов 3 стилей, в течении 5000 итераций с L1 регуляризацией, это заняло около 14 часов, но результат еще интереснее, фичи получились еще более локальные и чистые
![](https://habrastorage.org/storage2/e58/a13/b8d/e58a13b8d8ba21c15698e0dc476e5436.png)
![](https://habrastorage.org/storage2/d66/a16/0c1/d66a160c1d431983baab5e49fc3b2db2.png)