Автоэнкодеры: неконтролируемые искусственные нейронные сети (ИНС)

Добро пожаловать в этот блог об автокодировщиках. В этом блоге вы найдете объяснение того, что такое автоэнкодер, как он работает, и увидите реализацию автоэнкодера в TensorFlow.

Оглавление

  1. Введение
  2. Извлечение признаков и уменьшение размерности
  3. Структура автоэнкодера
  4. Представление
  5. Код

1. Введение

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

Статья 2006 года под названием Уменьшение размерности данных с помощью нейронных сетей, выполненная Г.Е. Хинтоном и Р.Р. Салахутдиновым, показала лучшие результаты, чем годы усовершенствования других типов сетей, и стала прорывом в области Нейронные сети.

«Автоэнкодеры, основанные на ограниченных машинах Больцмана, используются в некоторых из крупнейших приложений глубокого обучения. Они являются строительными блоками Deep Belief Networks (DBN)».

2. Извлечение признаков и уменьшение размерности

Пример приводит Нихил Будума в KdNuggets, в котором дается отличное объяснение полезности этого типа нейронной сети.

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

Но при использовании этой картинки мы начинаем сталкиваться с узким местом! Потому что это изображение размером 256x256 пикселей соответствует входному вектору размером 65536! Если бы мы использовали изображение, полученное с помощью обычных камер мобильных телефонов, это сгенерировало бы изображения размером 4000 пикселей. x 3000 пикселей, нам нужно будет проанализировать 12 миллионов размеров:

Как видите, она увеличивается экспоненциально! Возвращаясь к нашему примеру, нам не нужно использовать все 65 536 измерений для классификации эмоций. Человек идентифицирует эмоции по определенному выражению лица, некоторым ключевым чертам, таким как форма рта и брови.

3. Структура автоэнкодера

автоэнкодер можно разделить на две части:

1. Кодировщик :кодировщик должен сжимать представление ввода. В этом случае мы собираемся уменьшить размер лица нашего актера с 2000 до 30 размеров, пропустив данные через слои нашего кодировщика.

2. Декодер:декодер работает как сеть кодировщика в обратном порядке. Он работает, чтобы воссоздать ввод, как можно точнее. Это играет важную роль во время обучения, поскольку заставляет автоэнкодер выбирать наиболее важные функции в сжатом представлении.

4. Производительность

Это изображение было извлечено из сравнительной статьи Г. Э. Хинтона и Р. Р. Салахутдинова по двумерной редукции для 500 знаков MNIST, с PCA слева и автоэнкодером справа. Мы видим, что автоэнкодер обеспечил нам лучшее разделение данных.

5. Код

#from __future__ import division, print_function, absolute_import
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# Import MINST data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(“/tmp/data/”, one_hot=True)

Теперь давайте зададим параметры, которые будут использоваться нашей NN.

learning_rate = 0.01
training_epochs = 20
batch_size = 256
display_step = 1
examples_to_show = 10
# Network Parameters
n_hidden_1 = 256 # 1st layer num features
n_hidden_2 = 128 # 2nd layer num features
n_input = 784 # MNIST data input (img shape: 28*28)
# tf Graph input (only pictures)
X = tf.placeholder(“float”, [None, n_input])
weights = {
 ‘encoder_h1’: tf.Variable(tf.random_normal([n_input, n_hidden_1])),
 ‘encoder_h2’: tf.Variable(tf.random_normal([n_hidden_1, n_hidden_2])),
 ‘decoder_h1’: tf.Variable(tf.random_normal([n_hidden_2, n_hidden_1])),
 ‘decoder_h2’: tf.Variable(tf.random_normal([n_hidden_1, n_input])),
}
biases = {
 ‘encoder_b1’: tf.Variable(tf.random_normal([n_hidden_1])),
 ‘encoder_b2’: tf.Variable(tf.random_normal([n_hidden_2])),
 ‘decoder_b1’: tf.Variable(tf.random_normal([n_hidden_1])),
 ‘decoder_b2’: tf.Variable(tf.random_normal([n_input])),
}

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

# Building the Encoder
def encoder(x):
    # Encoder first layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['encoder_h1']), biases['encoder_b1']))
    # Encoder second layer with sigmoid activation #2
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1,  weights['encoder_h2']), biases['encoder_b2']))
    return layer_2

И декодер: вы можете видеть, что слой_1 в кодере — это слой_2 в декодере, и наоборот.

# Building the decoder
def decoder(x):
    # Decoder first layer with sigmoid activation #1
    layer_1 = tf.nn.sigmoid(tf.add(tf.matmul(x, weights['decoder_h1']),biases['decoder_b1']))
    # Decoder second layer with sigmoid activation #2
    layer_2 = tf.nn.sigmoid(tf.add(tf.matmul(layer_1, weights['decoder_h2']), biases['decoder_b2']))
    return layer_2

Давайте построим нашу модель. В переменной cost у нас есть функция потерь, а в переменной optimizer у нас есть наш градиент, используемый для обратного распространения.

# Launch the graph
# Using InteractiveSession (more convenient while using Notebooks)
sess = tf.InteractiveSession()
sess.run(init)
total_batch = int(mnist.train.num_examples / batch_size)
# Training cycle
for epoch in range(training_epochs):
 # Loop over all batches
 for i in range(total_batch):
 batch_xs, batch_ys = mnist.train.next_batch(batch_size)
 # Run optimization op (backprop) and cost op (to get loss value)
 _, c = sess.run([optimizer, cost], feed_dict={X: batch_xs})
 # Display logs per epoch step
 if epoch % display_step == 0:
 print(“Epoch:”, ‘%04d’ % (epoch+1),
 “cost=”, “{:.9f}”.format(c))
print(“Optimization Finished!”)

Вывод:

Epoch: 0001 cost= 0.182728916
Epoch: 0002 cost= 0.150434598
Epoch: 0003 cost= 0.130958572
Epoch: 0004 cost= 0.125098571
Epoch: 0005 cost= 0.119374141
Epoch: 0006 cost= 0.116029739
Epoch: 0007 cost= 0.114480294
Epoch: 0008 cost= 0.110542893
Epoch: 0009 cost= 0.107315414
Epoch: 0010 cost= 0.103023507
Epoch: 0011 cost= 0.101529025
Epoch: 0012 cost= 0.097410828
Epoch: 0013 cost= 0.093311585
Epoch: 0014 cost= 0.093811013
Epoch: 0015 cost= 0.090760238
Epoch: 0016 cost= 0.089178301
Epoch: 0017 cost= 0.087290406
Epoch: 0018 cost= 0.085913278
Epoch: 0019 cost= 0.086014777
Epoch: 0020 cost= 0.084903874
Optimization Finished!

Выше мы взяли 20 эпох.

Теперь давайте применим кодер и декодер для наших тестов.

# Applying encode and decode over test set
encode_decode = sess.run(
 y_pred, feed_dict={X: mnist.test.images[:examples_to_show]})
# Lets Let’s simply visualize our graphs!
# Compare original images with their reconstructions
f, a = plt.subplots(2, 10, figsize=(10, 2))
for i in range(examples_to_show):
 a[0][i].imshow(np.reshape(mnist.test.images[i], (28, 28)))
 a[1][i].imshow(np.reshape(encode_decode[i], (28, 28)))

Окончательный результат:

Как видите, реконструкция прошла успешно. Видно, что к изображению добавился шум.

Спасибо за чтение

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