Курс по нейронным сетям: https://stepik.org/a/227582
На предыдущем
занятии мы с вами познакомились с работой простого автоэнкодера, который
воспроизводил изображения цифр по вектору скрытого состояния. Давайте теперь
внимательнее посмотрим на область, которую формирует кодер при преобразовании
таких изображений. Для этого воспользуемся простой полносвязной НС с двумя
нейронами для описания вектора скрытого состояния:
В пакете Keras мы отдельно
опишем кодер и декодер и уже на их основе сформируем общий автоэнкодер:
input_img = Input(shape=(28, 28, 1))
x = Flatten()(input_img)
x = Dense(128, activation='relu')(x)
x = Dense(64, activation='relu')(x)
encoded = Dense(2, activation='linear')(x)
input_enc = Input(shape=(2,))
d = Dense(64, activation='relu')(input_enc)
d = Dense(28*28, activation='sigmoid')(d)
decoded = Reshape((28, 28, 1))(d)
encoder = keras.Model(input_img, encoded, name="encoder")
decoder = keras.Model(input_enc, decoded, name="decoder")
autoencoder = keras.Model(input_img, decoder(encoder(input_img)), name="autoencoder")
autoencoder.compile(optimizer='adam', loss='mean_squared_error')
Благодаря такой
конструкции мы теперь можем обучить автоэнкодер в целом:
autoencoder.fit(x_train, x_train, epochs=10, batch_size=64, shuffle=True)
А, затем,
отдельно использовать его кодер и декодер:
h = encoder.predict(x_test)
plt.scatter(h[:, 0], h[:, 1])
На графике
увидим следующее распределение точек векторов скрытого состояния для тестового
набора изображений:
Это характерная
картина формирования модельной области отображения входного сигнала в
пространство скрытого состояния. Что отсюда следует? Если мы будем брать точки
в пределах сформированной области, то скорее всего, на выходе декодера будут
получаться осмысленные изображения цифр. Если же брать точку за пределами этой
области, то очень вероятно получим какое-то неопределенное изображение.
Например, для точки с координатами
получим следующее изображение:
img = decoder.predict(np.expand_dims([50, 250], axis=0))
plt.imshow(img.squeeze(), cmap='gray')
Напоминает
шестерку, но выглядит не очень. Из-за этого автоэнкодеры в чистом виде не
пригодны для генерации произвольных изображений. То есть, мы не можем брать
произвольные точки в области скрытого состояния, чтобы гарантированно получать
осмысленные изображения. Чтобы решить эту проблему пространство состояний
скрытого вектора должно быть компактным и представлять единую цельную область
без существенных разделений. Именно эту цель преследуют вариационные
автоэнкодеры:
Variational Autoencoders (VAE)
Они пытаются
сформировать область точек скрытого пространства в соответствии с заданным
законом распределения. Часто выбирают нормальное (гауссовское) распределение,
так как оно наиболее просто с вычислительной точки зрения, имеет понятную,
приемлемую форму и полностью определяется двумя параметрами:
математическое
ожидание, дисперсия
Например, в
случае двумерного вектора скрытого пространства
,
будем требовать от кодера формирования распределения точек на плоскости в
соответствии с двумерной нормальной ПРВ:
Такой подход
даст нам уверенную надежду, что любая точка, взятая в пределах полученного
распределения, будет давать на выходе декодера осмысленные, понятные изображения.
То есть, мы будем понимать как выбирать точки в скрытом пространстве для
генерации новых полноценных изображений. Это ключевое отличие вариационного
автоэнкодера от обычных автоэнкодеров. Более того, эту же картину можно
интерпретировать как преобразование входного пространства большей размерности в
компактное скрытое пространство признаков меньшей размерности. Часто это
упрощает дальнейший анализ исходных данных.
Далее я приведу
теорию, необходимую для понимания построения вариационного автоэнкодера. Итак,
у нас есть формируемое и желаемое распределения точек скрытого пространства.
Обозначим их через
:
Задачей
алгоритма обучения будет не только точно воспроизвести входной сигнал, но и
распределить точки скрытого пространства как можно ближе к распределению
. Значит,
нам нужен критерий качества, который бы оценивал степень расхождения между
этими двумя распределениями:
и
. Благо
математики уже давно придумали такой критерий, он называется
дивергенция
Кульбака-Лейблера
(кому интересно,
хороший материал по этой мере изложен на этой странице https://habr.com/ru/post/484756/). Так как мы предполагаем, что
оба распределения будут гауссовскими с независимыми величинами вектора скрытого
состояния
то расстояние Кульбака-Лейблера
для этого случая записывается относительно просто, по следующей формуле:
Здесь
-
ковариационные матрицы вектора СВ. Например, для вектора h при условии
независимости его величин, ковариационная матрица будет иметь диагональный вид:
Здесь по главной
диагонали стоят дисперсии соответствующих величин. Вторая ковариационная
матрица желаемого распределения можно взять единичной:
Это будет
означать, что многомерная гауссовская ПРВ будет иметь одинаковые дисперсии по
всем направлениям (осям), равные 1. И вектор СВ состоит также из независимых
величин. Выбор такой ковариационной матрицы очень удобен, т.к. мы сможем ее
сократить в критерии качества Кульбака-Лейблера.
Далее, векторы
-
математическое ожидание для каждой из k величин:
Мы здесь для
желаемого нормального распределения МО всюду выбрали равные нулю. Это значит,
центр многомерного распределения
будет
находиться в начале координат. В итоге вектор
также
можно будет сократить. В результате, мера Кульбака-Лейблера для нашего частного
случая, станет следующей:
Если кто не
знает
-
- сумма
значений элементов главной диагонали матрицы (след матрицы);
-
- определитель
матрицы (для диагональной – произведение значений на главной диагонали).
Итак, мера
расхождения двух гауссовых ПРВ у нас есть. И эта мера зависит от векторов МО и
дисперсии:
Но кодер на выходе
выдает не эти величины, а непосредственно вектор скрытого состояния
Как же нам
вычислять МО и дисперсии текущего распределения и сделать так, чтобы алгоритм
обратного распространения ошибки мог использовать эту информацию при обучении VAE? Для этого
кодер будет формировать не сам вектор h, а векторы
:
Здесь генератор
НСВ выдает величины с нулевым вектором МО и единичными дисперсиями. Поэтому,
после поэлементного умножения на
и
сложением с
,
получим НСВ с этими характеристиками:
То есть, в
процессе обучения нейроны кодера будут выдавать векторы МО и дисперсии для
каждого входного наблюдения
. Но
откуда НС будет «знать», что одна группа нейронов – это МО, а другая –
дисперсии? Она такими категориями не «мыслит»! Это происходит по тем же
причинам, по которым, например, река течет строго по своему руслу:
Законы физики
«заставляют» ее течь по ложбинке, а не по возвышенностям. Также и при обучении
НС: нейроны приобретают те признаки, которым легче обучиться. Структура
вариационного автоэнкодера как раз способствует формированию МО и дисперсии на
этих группах нейронов. Это естественная магия работы НС.
Теперь, имея эти
оценки, можно использовать меру Кульбака-Лейблера для определения соответствия
текущего распределения заданному, а также еще один критерий для соответствия
входного сигнала выходному. То есть, в процессе обучения VAE будут
минимизироваться сразу два этих критерия. Первый будет способствовать
формированию правильного распределения векторов h скрытого
пространства. А второй – соответствию выходного сигнала входному. Здесь можно,
например, взять меру минимума среднего квадрата ошибок рассогласования:
где
-
вектор входного сигнала;
-
вектор выходного сигнала. Результирующий критерий будет равен сумме этих двух
величин:
На следующем
занятии мы реализует этот вариационный автоэнкодер и посмотрим к каким
результатам он приводит.
Курс по нейронным сетям: https://stepik.org/a/227582