Описание гауссовой смеси распределений и как её обучать

Описание гауссовой смеси распределений и как её обучать

Здравствуйте и вновь добро пожаловать на занятия по теме «Машинное обучение без учителя: скрытые марковские модели на языке Python» .

Следующая тема, которую мы обсудим, – это гауссовы смеси распределений.

Гауссовы смеси распределений – это одна из форм оценки плотности распределения. Они дают нам приближённое значение распределения вероятностей наших данных. Гауссовы смеси распределений используются в случае, когда обнаруживается, что наши данные имеют мультимодальное распределение, то есть имеют несколько «горбов». Как вы помните из теории вероятностей, мода – это наиболее часто встречаемое значение.

Гауссова смесь – это просто сумма всех взвешенных гауссиан. Для представления весовых коэффициентов вводится новый символ π. Например, πk означает вероятность того, что x принадлежит k-той гауссиане:

Обратите внимание, что существует ограничение – сумма всех π должна быть равной 1. Чтобы доказать это, используем тот факт, что все распределения вероятностей должны интегрироваться до 1. P(x) интегрируется до 1, и каждая гауссиана (поскольку мы знаем, что это действительные распределения) также интегрируется до 1. Таким образом, сумма всех π равна 1:

Другой способ представления – это введение новой скрытой переменной Z. Z показывает, какие данные представляет собой данная гауссиана. Можно записать:

\pi_k = P(Z = k).

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

Обучение гауссовой смеси распределений очень похоже на алгоритм метода k-средних. Оно проходит в два этапа, отражающих аналогичные этапы в методе k-средних.

Первый этап – расчёт принадлежностей. Для этого вводится новый символ γ.

\gamma^{(n)}_{k}

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

Как вы можете видеть, если πk будет большим, то данная гауссиана перекроет остальные и станет примерно равной единице.

Второй этап – перерасчёт всех параметров гауссиан – то есть среднего значения, ковариации и πk. Проводится он также очень похоже на метод k-средних. Мы взвешиваем влияние каждого примера на параметр через принадлежность. Если принадлежность мала, то и x в общем подсчёте будет мало значить:

Введение в Theano

В этой лекции мы рассмотрим основы библиотеки Theano. Мы рассмотрим Theano достаточно подробно, чтобы вы без особых проблем смогли создать собственную нейронную сеть, а в следующей лекции мы построим нейронную сеть с использованием Theano и проверим её на наших данных. Если вы хотите получить используемый в этой лекции код, перейдите по адресу https://github.com/lazyprogrammer/machine_learning_examples, найдите папку ann_class2 и в ней файл theano1.py.

Итак, запустим файл в Iphyton, чтобы вы могли видеть, что будет происходить. Дело в том, что множество новых идей и вещей будут работать не так, как можно было бы ожидать в обычном Phyton. Я не буду показывать, как установить Theano, поскольку это весьма несложно – просто зайдите на сайт и следуйте инструкциям. До сих пор я ни разу не слышал, чтобы у кого-то при этом возникали проблемы.

После этого первое, о чём мы поговорим, – это переменные Theano. Поскольку мы настолько часто будем использовать тензоры Theano, то будем обозначать библиотеку Theano через большое Т:

import theano.tensor as T

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

c = T.scalar(‘c’)

То же самое мы можем сделать для вектора:

v = T.vector(‘v’)

И для матрицы:

A = T.matrix(‘A’)

В Theano есть и тензоры, размерности которых достаточно равняться трём. Вы можете столкнуться с ними, если будете работать с неплоскими изображениями вроде тех, которыми мы уже пользовались. В таком случае у нас будет вектор длиной в 784 элемента, который должен быть переформатирован в размерность 28х28, чтобы иметь возможность просматривать изображения. Если вы хотите сохранить изображения в виде квадратов и у вас есть N изображений, то получится размерность Nx28x28, что и является трёхмерным тензором. Если же у вас есть три цветовых канала, например красный, зелёный и синий, то получится тензор с размерностью Nx3x28x28, являющийся четырёхмерным тензором. В этом курсе мы не будем работать с тензорами, поэтому это всё, что я хотел о них рассказать.

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

w = A.dot(v)

На самом деле никакой операции умножения мы не провели, поскольку она невозможна ввиду того, что ни A, ни v до сих пор не имеют никаких значений. Как же установить значения для A и v и найти результат w? Вот тут-то и вступают в игру функции Theano. Импортируем высокоуровневый модуль Theano, используя который, мы можем создавать функции Theano:

import theano

Каждое создание функции определяет входные и исходящие величины:

matrix_times_vector = theano.function(inputs=[A,v], outputs=w)

Импортируем теперь библиотеку Numpy, чтобы создать действительные массивы и вызвать функцию:

import numpy as np

A_val = np.array([[1,2], [3,4]])

v_val = np.array([5,6])

А вот так мы вызываем функцию и получаем ожидаемый результат:

w_val = matrix_times_vector(A_val, v_val)

print w_val

Пока что ничего особенного, не так ли?

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

В Theano обычные переменные являются необновляемыми. Для создания обновляемой переменной нам необходимо создать то, что называется общей переменной (shared variable). Этим и займёмся.

x = theano.shared(20.0, ‘x’)

Здесь первым параметром является первоначальное значение переменной, а вторым – её имя.

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

cost = x*x + x +1

Теперь давайте объясним Theano, как мы хотим обновить значение x, предложив выражение для обновления:

x_update = x – 0.3*T.grad(cost, x)

Что замечательно в Theano, так это то, что она автоматически вычисляет градиент. Функция grad имеет два параметра: первый – это функция, чей градиент мы хотим найти, а второй – переменная, относительно которой мы ищем градиент. При этом в качестве второго параметра вы можете подставить несколько переменных в виде списка.

Теперь давайте создадим простенькую обучающую функцию, похожую на предыдущую, но с тем исключением, что добавим в неё новый аргумент updates. Аргумент updates содержит список кортежей; каждый из кортежей включает два элемента: первый – обновляемая общая переменная, а второй – используемое для обновления выражение.

train = theano.function(inputs=□, outputs=cost, updates=[(x, x_update)])

Таким образом, в функции нет входных величин, и позже вы поймёте, почему.

Итак, мы создали функцию для обучения, но на самом деле ещё не вызвали. Обратите внимание, что x является не входной величиной, а величиной, которая будет обновляться. В дальнейших примерах входящими величинами будут данные и метки. Таким образом, параметр inputs использует данные и метки, а параметр updates использует параметры модели с их обновлениями.

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

for i in xrange(25):

    cost_val = train()

    print cost_val

Всё сошлось довольно быстро. Обратите внимание, что мы пришли к ожидаемому значению функции затрат и можем вывести на экран оптимальное значение x, использовав функцию get_value:

x.get_value()

Это значение и ожидалось.

А наш курс подошел к концу, надеюсь вам было интересно и вы узнали что-то новое!

Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: