8 апреля 2013 в 12:38

Регуляризация в ограниченной машине Больцмана, эксперимент

Привет. В этом посте мы проведем эксперимент, в котором протестируем два типа регуляризации в ограниченной машине Больцмана. Как оказалось, RBM очень чувствительна к параметрам модели, таким как момент и локальное поле нейрона (более подробно обо всех параметрах можно прочитать в практическом руководстве в RBM Джеффри Хинтона). Но мне для полной картины и для получения шаблонов наподобие таких вот, не хватало еще одного параметра — регуляризации. К ограниченным машинам Больцмана можно относиться и как к разновидности сети Маркова, и как к очередной нейроной сети, но если копнуть глубже, то будет видна аналогия и со зрением. Подобно первичной зрительной коре, получающей информацию от сетчатки через зрительный нерв (да простят меня биологи за такое упрощение), RBM ищет простые шаблоны во входном изображении. На этом аналогия не заканчивается, если очень малые и нулевые веса интерпретировать как отсутствие веса, то мы получим, что каждый скрытый нейрон RBM формирует некоторое рецептивное поле, а сформированная из обученных RBM глубокая сеть формирует из простых образов более комплексные признаки; чем-то подобным, в принципе, и занимается зрительная кора головного мозга, правда, вероятно, как то посложнее =)



L1 и L2 регуляризация


Начнем мы, пожалуй, с краткого описания того, что такое регуляризация модели — это способ наложить штраф к целевой функции за сложность модели. С байесовской точки зрения — это способ учесть некоторую априорную информацию о распределении параметров модели. Важным свойством является то, что регуляризация помогает избежать переобучения модели. Обозначим параметры модели как θ = {θ_i}, i=1..n. Итоговая целевая функция C = η(E + λR), где E — это основная целевая функция модели, R = R(θ) — функция от параметров модели, эта и лямбда — это скорость обучения и параметр регуляризации соответственно. Таким образом, для вычисления градиента итоговой целевой функции будет необходимо вычислить градиент функции регуляризации:



Мы рассмотрим два вида регуляризации, корни которых находятся в Lp метрике. Функция регуляризации L1 и ее производные имеют следующий вид:





L2 регулярицазия выглядит следующим образом:





Оба метода регуляризации штрафуют модель за большое значение весов, в первом случае абсолютными значениями весов, во втором квадратами весов, таким образом, распределение весов будет приближаться к нормальному с центром в нуле и большим пиком. Более подробное сравнение L1 и L2 можно почитать тут. Как мы позже увидим, около 70% весов будут меньше 10^(-8).

Регуляризация в RBM


В позапрошлом посте я описывал пример реализации RBM на C#. Я буду опираться на ту же реализацию для того, чтобы показать, куда встраивается регуляризация, но сначала формулы. Целью обучения RBM является максимизация вероятности того, что восстановленный образ будет идентичен входному:

image

Вообще говоря, в алгоритме максимизируется логарифм вероятности, и чтобы внести штраф, необходимо вычесть значение функции регуляризации из полученной вероятности, в итоге новая целевая функция приобретает следующий вид:



Производная такой функции по параметру будет выглядить так:



Алгоритм 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 эпох. Я буду приводить два способа визуализации найденных шаблонов, в первом случае (рисунок в серых тонах) темное значение соответствует минимальному значению веса, а белый максимальному; во втором рисунке черный соответствует нулю, увеличение красной составляющей соответствует увеличению в положительную сторону, а увеличение синей составляющей — в отрицательную. Так же я буду приводить гистограмму распределения весов и небольшие комментарии.

Без регуляризации






  • значение ошибки на обучающем наборе: 0.188181367765024
  • значение ошибки на кроссвалидационном наборе: 21.0910315518859


Шаблоны получились очень размытые, и трудно анализируемые. Среднее значение весов сдвинуто влево, а абсолютное значение весов достигает 2 и более.

L2 регуляризация






  • значение ошибки на обучающем наборе: 10.1198906337165
  • значение ошибки на кроссвалидационном наборе: 23.3600809429977
  • параметр регуляризации: 0.1


Здесь мы наблюдаем более четкие образы. Мы уже можем разглядеть, что на некоторых образах действительно учитываются какие-то особенности букв. Несмотря на то, что ошибка на обучающем наборе в 100 раз хуже, чем при обучении без регуляризации, ошибка на кроссвалидационном множестве не намного превышает первый эксперимент, что говорит о том, что обобщающая способность сети на незнакомых образах не сильно ухудшилась (стоит заметить, что в подсчет ошибки не включалось значение функции регуляризации, что позволяет нам сравнивать значения с предыдущем опытом). Веса сконцентрированы вокруг нуля, и не сильно превышают 0.2 по абсолютному значению, что в 10 раз меньше, чем в предыдущем опыте.

L1 регуляризация






  • значение ошибки на обучающем наборе: 4.42672814826447
  • значение ошибке на кроссвалидационном наборе: 17.3700437102876
  • параметр регуляризации: 0.005


В данном опыте мы наблюдаем четкие шаблоны, а в особенности рецептивные поля (вокруг сине-красных пятен все веса почти равны нулю). Шаблоны даже поддаются анализу, мы можем заметить, например, ребра от W (первый ряд четвертая картинка), или же шаблон, который отражает средний размер входных образов (в пятом ряду 8 и 10 картинка). Ошибка восстановления на обучающем множестве в 40 раз хуже чем в первом эксперименте, но лучше чем при L2 регуляризации, в то же время ошибка на неизвестном множестве лучше, чем в обоих предыдущих опытах, что говорит о еще лучшей обобщающей способности. Веса так же сконцентрированы вокруг нуля, и в большинстве случаев не сильно его превышают. Существенное отличие в параметре регуляризации объясняется тем, что при вычислении градиента для L2 параметр умножается на значение веса, как правило эти оба числа меньше 1; но при L1 параметр умножается на |1|, и и итоговое значение будет того же порядка что и параметр регуляризации.

Заключение


В качестве заключения хочется сказать что РБМ действительно очень чувствительная к параметрам вещь. И главное — не сломаться в процессе поиска решения -) В конце приведу увеличенное излбражение одной из RBM тренировавшихся с L1 регуляризацией, но уже в течении 5000 эпох.


UPDATE:
недавно обучил рбм на полном наборе больших букв 4 шрифтов 3 стилей, в течении 5000 итераций с L1 регуляризацией, это заняло около 14 часов, но результат еще интереснее, фичи получились еще более локальные и чистые

+21
12363
143

Комментарии (15)

+9
juneuniversum, #
Последняя картинка конечно многое объясняет…
НЛО прилетело и опубликовало эту надпись здесь
+1
mephistopheies, #
вот тут я на шарпе делал habrahabr.ru/post/154369/
если интересно более подробно то можешь послушать курс Хинтона class.coursera.org/neuralnets-2012-001/class/index, там на матлабе, и конечно это выглядит более естественно чем на ооп языке

нужно создать нейроны и обозначить их связи.

если на ооп языке то да, можно нейроны, связи, будет выглядить прямо как нейросеть, прикольно. но по сути это все матричные вычисления, и если писать на матлабе то можно обойтись вообще без структур типа нейрона.
НЛО прилетело и опубликовало эту надпись здесь
0
mephistopheies, #
это нужно было бы отдельный пост писать, тем более что есть более качественные ресурсы типа Хинтоновского курса на курсере, еще можно послужать курс Andrew Ng там же; и там и там отлично все описано, по мимо этого есть еще домашки на матлабе
+6
mifki, #
Ничего не понял, положу в закладки…
0
mephistopheies, #
хехе -) не ну да всякое в жизни бывает
0
Ariman, #
А стохастические НС обучают чем-нибудь вроде генетического алгоритма?
Каковы результаты в этом случае? До того, как я прочитал про подобные нейросети мне самому пришла в голову идея заменить стандартную функцию активации в нейронах многослойного перцептрона на функцию, которая выдает значение на выходе с некоторой вероятностью, зависящей от входного потенциала. Сейчас читаю ваши статьи и понимаю, что это и есть стохастические НС. Однако, когда я думал о такой сети, меня, конечно, не хватило на то, чтобы придумать такой хардкорный алгоритм их тренировки, какой применяется для машин Больцмана, поэтому оптимальным выходом я тогда счел алгоритмы типа генетических, но, к сожалению, так это и не попробовал.
Вы не пробовали?
И еще вопрос — не пробовали комбинировать слои? Стохастические с обычными, детерменированными, допустим?
0
mephistopheies, #
А стохастические НС обучают чем-нибудь вроде генетического алгоритма? Вы не пробовали?

нет, обучается обычным градиентным подъемом по функции log likelihood вероятности восстановления образа, можно тут глянуть habrahabr.ru/post/159909/. алгоритм придуман Джефри Хинтоном

я пробовал обучать РБМ генетическим алгоритмом, результат есть, но в разы хуже Хинтоновского contrastive divergence. хотя я дилетант в генетических алгоритмах, и если построить операторы скрещевания и мутации как нибудь по умнее, то возможно что то и получится

И еще вопрос — не пробовали комбинировать слои? Стохастические с обычными, детерменированными, допустим?

суть глубокого обучения нейросети и есть комбинация обучения без учителя и с учтелем, сначала строится архитектура сети, затем предобучаются попарно идущие слои в виде РБМ, а затем обучается вся сеть обратным распространением с учителем. результат получается на много лучше нежели не предобученная сеть, можно глянуть сюда habrahabr.ru/post/163819/ и вот сюда deeplearning.net/

уже есть ряд людей который исследуют применение РБМ в задачах классификации, вот там как раз идет речь о том что ты имеешь в виду, реальное комбинирование в процессе обучения, а не последовательное применение сначала РБМ а затем обучения с учителем. например вот machinelearning.org/archive/icml2008/papers/601.pdf. по сути чувак взял ту же целевую функцию что и в обучении без учителя (приближенное значение производной которой дает contrastive divergence) и добавил в нее слагаемое отвечающее за классификацию, нашел производные своего слогаемого, объединил с оригинальным алгоритмом ну и получил свою статью. я его алгоритм еще не пробовал тестить, так что не могу объективно судить о качестве, но чисто интуитивно мне глубокие предобученые сети нравятся больше.
0
Ariman, #
Просто есть задачи, в которых вряд ли получится применить другие методы обучения — предположим, задача обучить НС, которая используется в качестве блока, который принимает высокоуровневые решения в игре.
То есть, у нас есть набор действий, которые доступны боту — скажем, выстрелить из текущего оружия, выбрать оружие N, активировать способность M, переместиться в указанную точку. (За низкоуровневую обработку того же «переместиться» отвечает, понятное дело, стандартный алгоритм поиска пути, нечего сеть нагружать этой ерундой).
И есть набор данных, идущих на вход — свое здоровье, запас патронов, список объектов в обозримом радиусе, их классы, скорость и вектор движения.

Сюда для обучения отлично подходит генетический алгоритм, т.к. «правильного», формализованного решения не существует, зато есть возможность сталкивать сотнями этих ботов и отбирать лучших.

Многослойный перцептрон полностью детерминирован, поэтому боты будут вести себя всегда одинаково при одинаковых входных параметрах. Я предполагаю, что добавление вероятностной функции активации должно значительно улучшить результаты.
0
mephistopheies, #
вот кстати интересный эксперимент описан habrahabr.ru/post/168067/, как раз прочитав эту статью, я решил попробовать обучить рбм генетическим алгоритмом

кстати на счет детерминированности, это то действительно так, но какова вероятность того что на вход поступят одинаковые входные векторы (свое здоровье, запас патронов, список объектов в обозримом радиусе, их классы, скорость и вектор движения), ну скажем то что в одной точке пространства окажется объект с одним и тем же вектором скорости и набором остальных параметров. конечно тут все зависет от игры. но в общем случае я не стал бы так сразу опасаться детерминированности. но если скажем такое случается крайне редко, то наверное ничего страшного в предопределенности нет.

с другой стороны можно интерпретировать выход сети как вероятности. скажем у тебя на выходе три нейрона, каждый является индикатором экшена, и ты не просто выбираешь тот что с максимальным выходом, а пропорционально их проецируешь на отрезок [0, 1] и генеришь рандомное число в этом промежутке из равномерного распределения, в итоге получаешь действие но как бы уже с долей случайности.
0
Ariman, #
>с другой стороны можно интерпретировать выход сети как вероятности

Это именно те размышления, которые привели меня к идее вероятностного нейрона) Я как раз и подумал сначала — «почему бы не отказаться от выбора самого активного выхода, а выбирать из них пропорционально активности». Следующей мыслью как раз и стало интегрировать эту вероятностную сущность в сам нейрон…

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

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


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

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

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

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


кстати как вариант можно вот что использовать, в общем часто используют сразу несколько моделей которые либо голосуют за решение, либо используется бустинг для создания комплексной модели. но в твоем случае, как мне кажется, интересным способом моделирования мозговых процессов будет следующее: у тебя есть множество входных параметров скажем их 100 штук, ты делаешь из него сэмплинг без возвратов скажем 80 признаков, ну или как нибудь эвристически выбираешь такие признаки. а затем обучаешь некоторое количество моделей на не полных данных. затем они голосуют. как то так -)
+1
Ariman, #
>а в описанном выше случае, нейроны рассматриваются как вполне детерминистические. а уже после обучения мы интерпретируем выходы нейронов как хотим.

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

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