Автоэнкодер в TensorFlow с примером

Что такое автоэнкодер в глубоком обучении?

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

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

Как работает автоэнкодер TensorFlow?

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

Типичный автоэнкодер определяется входом, внутренним представлением и выходом (аппроксимацией входа). Обучение происходит на уровнях, связанных с внутренним представлением. Фактически, существует два основных блока слоев, которые выглядят как традиционная нейронная сеть. Небольшая разница заключается в том, что слой, содержащий выходные данные, должен быть равен входному. На рисунке ниже исходный ввод попадает в первый блок, называемый кодер. Это внутреннее представление сжимает (уменьшает) размер входных данных. Во втором блоке происходит реконструкция ввода. Это этап декодирования.

Работа автоэнкодера
Работа автоэнкодера

Работа автоэнкодера

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

Конкретно, представьте себе картинку размером 50х50 (т.е. 250 пикселей) и нейронную сеть всего с одним скрытым слоем, состоящим из ста нейронов. Обучение осуществляется на карте объектов, которая в два раза меньше входных данных. Это означает, что сети необходимо найти способ восстановить 250 пикселей, используя только вектор нейронов, равный 100.

Пример составного автоэнкодера

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

В настоящее время автоэнкодеры в Глубокое обучение в основном используются для шумоподавления изображения. Представьте себе изображение с царапинами; человек все еще способен распознавать контент. Идея шумоподавления автоэнкодера состоит в том, чтобы добавить к изображению шум, чтобы заставить сеть изучить закономерность, лежащую в основе данных.

Другое полезное семейство автоэнкодеров глубокого обучения — это вариационные автоэнкодеры. Этот тип сети может генерировать новые изображения. Представьте, что вы тренируете сеть с изображением мужчины; такая сеть может создавать новые лица.

Как создать автоэнкодер с помощью TensorFlow

В этом уроке вы узнаете, как создать составной автокодировщик для восстановления изображения.

Вы будете использовать Набор данных CIFAR-10 который содержит 60000 32 цветных изображений размером 32×50000. Набор данных автоэнкодера уже разделен на 10000 XNUMX изображений для обучения и XNUMX XNUMX для тестирования. Всего до десяти классов:

  • Самолет
  • Автомобили
  • Птица
  • Кошка
  • Олень
  • Собака
  • лягушка
  • Лошадь
  • Адрес доставки
  • Грузовики

Вам необходимо загрузить изображения по этому URL https://www.cs.toronto.edu/~kriz/cifar.html и разархивировать их. Папка for-10-batches-py содержит пять пакетов данных по 10000 XNUMX изображений в каждом в случайном порядке.

Прежде чем создавать и обучать свою модель, вам необходимо применить некоторую обработку данных. Вы будете действовать следующим образом:

  1. Импортировать данные
  2. Преобразуйте данные в черно-белый формат.
  3. Добавить все пакеты
  4. Создайте набор обучающих данных
  5. Создайте визуализатор изображений

Предварительная обработка изображений

Шаг 1) Импортируйте данные

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

import numpy as np
import tensorflow as tf
import pickle
def unpickle(file):
    import pickle
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='latin1')
    return dict

Шаг 2) Преобразуйте данные в черно-белый формат.

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

def grayscale(im):
    return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)

Шаг 3) Добавьте все пакеты

Теперь, когда обе функции созданы и набор данных загружен, вы можете написать цикл для добавления данных в память. Если вы внимательно проверите, распакованный файл с данными будет называться data_batch_ и иметь номер от 1 до 5. Вы можете перебирать файлы и добавлять их к данным.

Когда этот шаг будет выполнен, вы преобразуете данные о цветах в формат шкалы серого. Как видите, форма данных — 50000 1024 и 32. 32*2014 пикселя теперь выравниваются до XNUMX года.

# Load the data into memory
data, labels = [], []
## Loop over the b
for i in range(1, 6):
    filename = './cifar-10-batches-py/data_batch_' + str(i)
    open_data = unpickle(filename)
    if len(data) > 0:
        data = np.vstack((data, open_data['data']))
        labels = np.hstack((labels, open_data['labels']))
    else:
        data = open_data['data']
        labels = open_data['labels']

data = grayscale(data)
x = np.matrix(data)
y = np.array(labels)
print(x.shape)
(50000, 1024)

Примечание. Измените «./cifar-10-batches-py/data_batch_» на фактическое местоположение вашего файла. Например, для Windows машине, путь может быть filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)

Шаг 4) Создайте набор обучающих данных

Чтобы обучение проходило быстрее и проще, вы будете тренировать модель только на изображениях лошадей. Лошади относятся к седьмому классу в данных этикетки. Как упоминается в документации набора данных CIFAR-10, каждый класс содержит 5000 изображений. Вы можете распечатать форму данных, чтобы подтвердить наличие 5.000 изображений с 1024 столбцами, как показано ниже. TensorFlow Пример шага автоэнкодера.

horse_i = np.where(y == 7)[0]
horse_x = x[horse_i]
print(np.shape(horse_x)) 
(5000, 1024)

Шаг 5) Создайте визуализатор изображений

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

Простой способ распечатать изображения — использовать объект imshow из библиотеки matplotlib. Обратите внимание, что вам необходимо преобразовать форму данных из 1024 в 32*32 (т.е. формат изображения).

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
def plot_image(image, shape=[32, 32], cmap = "Greys_r"):
    plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest")
    plt.axis("off")   

Функция принимает 3 аргумента:

  • Фото товара: вход
  • Форма: список, размер изображения
  • Карта:выберите карту цветов. По умолчанию серый

Вы можете попытаться построить первое изображение в наборе данных. Вы должны увидеть человека на лошади.

plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")

Создайте визуализатор изображений

Установить оценщик набора данных

Хорошо, теперь, когда набор данных готов к использованию, вы можете начать использовать Tensorflow. Прежде чем строить модель, давайте воспользуемся оценщиком набора данных Tensorflow для питания сети.

Вы создадите набор данных с помощью оценщика TensorFlow. Чтобы освежить свой разум, вам нужно использовать:

  • from_tensor_slices
  • повторять
  • партия

Полный код для создания набора данных:

dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)

Обратите внимание, что x — это заполнитель следующей формы:

  • [None,n_inputs]: установите значение «Нет», поскольку количество изображений, передаваемых в сеть, равно размеру пакета.

для получения подробной информации, пожалуйста, обратитесь к руководству по линейная регрессия.

После этого вам нужно создать итератор. Без этой строки кода никакие данные не будут проходить через конвейер.

iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()

Теперь, когда конвейер готов, вы можете проверить, такое ли первое изображение, как раньше (т. е. человек на лошади).

Вы устанавливаете размер пакета равным 1, потому что хотите передать набор данных только одним изображением. Вы можете увидеть размерность данных с помощью print(sess.run(features).shape). Оно равно (1, 1024). 1 означает, что подается только одно изображение с 1024 изображениями каждое. Если размер пакета установлен на два, то через конвейер пройдут два изображения. (Не меняйте размер пакета. В противном случае будет выдана ошибка. В функциюplot_image() одновременно может передаваться только одно изображение.

## Parameters
n_inputs = 32 * 32
BATCH_SIZE = 1
batch_size = tf.placeholder(tf.int64)

# using a placeholder
x = tf.placeholder(tf.float32, shape=[None,n_inputs])
## Dataset
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
iter = dataset.make_initializable_iterator() # create the iterator
features = iter.get_next()

## Print the image
with tf.Session() as sess:
    # feed the placeholder with data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                         batch_size: BATCH_SIZE}) 
    print(sess.run(features).shape) 
    plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r")
(1, 1024)

Установить оценщик набора данных

Создайте сеть

Настало время построить сеть. Вы обучите составной автокодировщик, то есть сеть с несколькими скрытыми слоями.

Ваша сеть будет иметь один входной слой с 1024 точками, т. е. размером 32×32, формой изображения.

Блок кодера будет иметь один верхний скрытый слой с 300 нейронами и центральный слой со 150 нейронами. Блок декодера симметричен кодировщику. Вы можете визуализировать сеть на рисунке ниже. Обратите внимание, что вы можете изменить значения скрытых и центральных слоев.

Постройте сеть
Создание сети для автоэнкодера

Создание автоэнкодера очень похоже на любую другую модель глубокого обучения.

Вы построите модель, выполнив следующие действия:

  1. Определите параметры
  2. Определите слои
  3. Определите архитектуру
  4. Определите оптимизацию
  5. Запустите модель
  6. Оцените модель

В предыдущем разделе вы узнали, как создать конвейер для подачи модели, поэтому нет необходимости создавать набор данных еще раз. Вы создадите автоэнкодер с четырьмя слоями. Вы используете инициализацию Xavier. Это метод установки начальных весов, равных дисперсии входных и выходных данных. Наконец, вы используете функцию активации elu. Вы регуляризуете функцию потерь с помощью регуляризатора L2.

Шаг 1) Определите параметры

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

Перед этим вы частично импортируете функцию. Это лучший метод определения параметров плотных слоев. Код ниже определяет значения архитектуры автоэнкодера. Как упоминалось ранее, автоэнкодер имеет два слоя: 300 нейронов в первых слоях и 150 во вторых. Их значения хранятся в n_hidden_1 и n_hidden_2.

Вам необходимо определить скорость обучения и гиперпараметр L2. Значения хранятся в Learning_rate и l2_reg.

from functools import partial

## Encoder
n_hidden_1 = 300
n_hidden_2 = 150  # codings

## Decoder
n_hidden_3 = n_hidden_1
n_outputs = n_inputs

learning_rate = 0.01
l2_reg = 0.0001

Техника инициализации Xavier вызывается с помощью объекта xavier_initializer из вклада средства оценки. В том же оценщике вы можете добавить регуляризатор с помощью l2_regularizer.

## Define the Xavier initialization
xav_init =  tf.contrib.layers.xavier_initializer()
## Define the L2 regularizer
l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)

Шаг 2) Определите слои

Все параметры плотных слоев заданы; вы можете упаковать все в переменную Density_layer, используя партиал объекта. Density_layer, который использует активацию ELU, инициализацию Xavier и регуляризацию L2.

## Create the dense layer
dense_layer = partial(tf.layers.dense,
                         activation=tf.nn.elu,
                         kernel_initializer=xav_init,
                         kernel_regularizer=l2_regularizer)

Шаг 3) Определите архитектуру

Если вы посмотрите на изображение архитектуры, то заметите, что сеть состоит из трех слоев с выходным слоем. В приведенном ниже коде вы соединяете соответствующие слои. Например, первый слой вычисляет скалярное произведение между признаками входной матрицы и матрицами, содержащими 300 весов. После вычисления скалярного произведения выходные данные передаются в функцию активации Elu. Выходные данные становятся входными данными следующего слоя, поэтому вы используете их для вычисления скрытого_2 и так далее. Умножение матриц одинаково для каждого слоя, поскольку вы используете одну и ту же функцию активации. Обратите внимание, что последний слой — выходные данные — не применяет функцию активации. Это имеет смысл, потому что это восстановленный входной сигнал.

## Make the mat mul
hidden_1 = dense_layer(features, n_hidden_1)
hidden_2 = dense_layer(hidden_1, n_hidden_2)
hidden_3 = dense_layer(hidden_2, n_hidden_3)
outputs = dense_layer(hidden_3, n_outputs, activation=None)

Шаг 4) Определите оптимизацию

Последний шаг — создание оптимизатора. В качестве функции потерь вы используете среднеквадратическую ошибку. Если вы помните учебник по линейной регрессии, вы знаете, что MSE вычисляется на основе разницы между прогнозируемым выходным сигналом и реальной меткой. Здесь метка является признаком, поскольку модель пытается восстановить входные данные. Следовательно, вам нужно среднее значение суммы разности квадратов между прогнозируемыми выходными и входными данными. С помощью TensorFlow вы можете закодировать функцию потерь следующим образом:

loss = tf.reduce_mean(tf.square(outputs - features))

Затем вам необходимо оптимизировать функцию потерь. Вы используете оптимизатор Адама для вычисления градиентов. Целевая функция – минимизировать потери.

## Optimize
loss = tf.reduce_mean(tf.square(outputs - features))
optimizer = tf.train.AdamOptimizer(learning_rate)
train  = optimizer.minimize(loss)

Еще одна настройка перед обучением модели. Вы хотите использовать размер пакета 150, то есть загружать в конвейер 150 изображений на каждой итерации. Вам необходимо вычислить количество итераций вручную. Это тривиально сделать:

Если вы хотите передавать 150 изображений каждый раз и знаете, что в наборе данных 5000 изображений, количество итераций равно . В Python вы можете запустить следующие коды и убедиться, что результат равен 33:

BATCH_SIZE = 150
### Number of batches :  length dataset / batch size
n_batches = horse_x.shape[0] // BATCH_SIZE
print(n_batches)
33

Шаг 5) Запустите модель

И последнее, но не менее важное: обучите модель. Вы обучаете модель на 100 эпохах. То есть модель будет видеть в 100 раз больше изображений с оптимизированным весом.

Вы уже знакомы с кодами для обучения модели в Tensorflow. Небольшая разница заключается в передаче данных перед запуском обучения. Таким образом модель тренируется быстрее.

Вам интересно распечатать потери через десять эпох, чтобы увидеть, учится ли модель чему-то (т. е. уменьшаются ли потери). Обучение занимает от 2 до 5 минут, в зависимости от аппаратного обеспечения вашего компьютера.

## Set params
n_epochs = 100

## Call Saver to save the model and re-use it later during evaluation
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    # initialise iterator with train data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                          batch_size: BATCH_SIZE})
    print('Training...')
    print(sess.run(features).shape) 
    for epoch in range(n_epochs):       
        for iteration in range(n_batches):
            sess.run(train)
        if epoch % 10 == 0:
            loss_train = loss.eval()   # not shown
            print("\r{}".format(epoch), "Train MSE:", loss_train) 
        #saver.save(sess, "./my_model_all_layers.ckpt") 
    save_path = saver.save(sess, "./model.ckpt")    
    print("Model saved in path: %s" % save_path)  
Training...
(150, 1024)
0 Train MSE: 2934.455
10 Train MSE: 1672.676
20 Train MSE: 1514.709
30 Train MSE: 1404.3118
40 Train MSE: 1425.058
50 Train MSE: 1479.0631
60 Train MSE: 1609.5259
70 Train MSE: 1482.3223
80 Train MSE: 1445.7035
90 Train MSE: 1453.8597
Model saved in path: ./model.ckpt

Шаг 6) Оцените модель

Теперь, когда ваша модель обучена, пришло время ее оценить. Вам необходимо импортировать тестовый сертификат из файла /cifar-10-batches-py/.

test_data = unpickle('./cifar-10-batches-py/test_batch')
test_x = grayscale(test_data['data'])
#test_labels = np.array(test_data['labels'])

ЗАМЕТКА: Для Windows машине код становится test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)

Вы можете попробовать распечатать картинку 13, на которой изображена лошадь.

plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")

Оцените модель

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

Функция принимает два аргумента:

  • df: Импортировать тестовые данные
  • номер_изображения: укажите, какое изображение импортировать

Функция разделена на три части:

  1. Измените форму изображения до правильного размера, например 1, 1024.
  2. Снабдите модель невидимым изображением, закодируйте/декодируйте изображение.
  3. Распечатайте реальное и реконструированное изображение
def reconstruct_image(df, image_number = 1):
    ## Part 1: Reshape the image to the correct dimension i.e 1, 1024
    x_test = df[image_number]
    x_test_1 = x_test.reshape((1, 32*32))
    
    ## Part 2: Feed the model with the unseen image, encode/decode the image
    with tf.Session() as sess:     
        sess.run(tf.global_variables_initializer()) 
        sess.run(iter.initializer, feed_dict={x: x_test_1,
                                      batch_size: 1})
    ## Part 3:  Print the real and reconstructed image
      # Restore variables from disk.
        saver.restore(sess, "./model.ckpt")  
        print("Model restored.")
      # Reconstruct image
        outputs_val = outputs.eval()
        print(outputs_val.shape)
        fig = plt.figure()
      # Plot real
        ax1 = fig.add_subplot(121)
        plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")
      # Plot estimated
        ax2 = fig.add_subplot(122)
        plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r")
        plt.tight_layout()
        fig = plt.gcf()

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

reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt
Model restored.
(1, 1024)

Оцените модель

Итого

  • Основная цель автокодировщика — сжать входные данные, а затем распаковать их в выходные данные, которые очень похожи на исходные данные.
  • Архитектура автоэнкодера симметрична со сводным слоем, называемым центральным уровнем.
  • Вы можете создать автоэнкодер, используя:
  • Частичный: для создания плотных слоев с типичными настройками:

      	tf.layers.dense,                         
      	activation=tf.nn.elu,                         
      	kernel_initializer=xav_init,                         
      	kernel_regularizer=l2_regularizer

    плотный_слой(): сделать матричное умножение

  • Вы можете определить функцию потерь и оптимизацию с помощью:
  • loss = tf.reduce_mean(tf.square(outputs - features))
    optimizer = tf.train.AdamOptimizer(learning_rate)
    train  = optimizer.minimize(loss)
    
  • Последний запуск сеанса для обучения модели.