Автокодер у TensorFlow із прикладом
Що таке Autoencoder у Deep Learning?
An Автокодер це інструмент для ефективного вивчення кодування даних без нагляду. Це тип штучної нейронної мережі, яка допомагає навчитися представленню наборів даних для зменшення розмірності, навчаючи нейронну мережу ігнорувати шум сигналу. Це чудовий інструмент для відтворення введення.
Простіше кажучи, машина приймає, скажімо, зображення, і може створювати тісно пов’язане зображення. Вхідні дані в цьому типі нейронної мережі не позначені, тобто мережа здатна навчатися без нагляду. Точніше, вхідні дані кодуються мережею, щоб зосередитися лише на найважливішій функції. Це одна з причин, чому автокодер популярний для зменшення розмірності. Крім того, для виробництва можна використовувати автокодери генеративні моделі навчання. Наприклад, нейронну мережу можна навчити з набором облич, а потім створити нові обличчя.
Як працює TensorFlow Autoencoder?
Метою автокодувальника є створення наближення вхідних даних, зосереджуючись лише на основних характеристиках. Ви можете подумати, чому б просто не навчитися копіювати та вставляти вхідні дані для отримання результату. Насправді автокодер — це набір обмежень, які змушують мережу вивчати нові способи представлення даних, відмінні від простого копіювання виводу.
Типовий автокодер визначається входом, внутрішнім представленням і виходом (наближенням входу). Навчання відбувається в шарах, приєднаних до внутрішнього представлення. Насправді є два основних блоки шарів, які виглядають як традиційна нейронна мережа. Невелика різниця полягає в тому, що шар, що містить вихід, повинен бути рівним входу. На малюнку нижче оригінальний вхідний сигнал переходить у перший блок під назвою кодіровщік. Це внутрішнє представлення стискає (зменшує) розмір вхідних даних. У другому блоці відбувається реконструкція входу. Це етап декодування.
Модель оновить ваги шляхом мінімізації функції втрат. Модель штрафується, якщо вихідні дані реконструкції відрізняються від вхідних.
Конкретніше, уявіть картинку розміром 50×50 (тобто 250 пікселів) і нейронну мережу лише з одним прихованим шаром, що складається зі ста нейронів. Навчання виконується на карті функцій, яка вдвічі менша за вхідні дані. Це означає, що мережі потрібно знайти спосіб реконструювати 250 пікселів лише з вектором нейронів, що дорівнює 100.
Приклад стекового автокодувальника
У цьому підручнику Autoencoder ви дізнаєтеся, як використовувати стековий автокодер. Архітектура схожа на традиційну нейронну мережу. Вхідні дані надходять до прихованого шару для стиснення або зменшення його розміру, а потім досягають шарів реконструкції. Мета полягає в тому, щоб отримати вихідне зображення так само близько до оригінального. Модель має навчитися досягати свого завдання за набору обмежень, тобто з меншою розмірністю.
Зараз автокодери в Глибоке навчання в основному використовуються для зменшення шуму зображення. Уявіть собі зображення з подряпинами; людина все ще здатна розпізнати вміст. Ідея усунення шумів у автокодері полягає в додаванні шуму до зображення, щоб змусити мережу дізнатися шаблон, що стоїть за даними.
Іншим корисним сімейством Autoencoder Deep Learning є варіаційний автокодер. Цей тип мережі може створювати нові зображення. Уявіть, що ви тренуєте мережу із зображенням людини; така мережа може створити нові обличчя.
Як створити автокодер із TensorFlow
У цьому підручнику ви дізнаєтеся, як побудувати стековий автокодер для реконструкції зображення.
Ви будете використовувати Набір даних CIFAR-10 який містить 60000 кольорових зображень 32×32. Набір даних Autoencoder уже розділений на 50000 10000 зображень для навчання та XNUMX XNUMX для тестування. Є до десяти класів:
- Літак
- автомобіль
- Птах
- Кішка
- Олень
- Пес
- Жаба
- Кінь
- Судно
- Вантажні автомобілі
Вам потрібно завантажити зображення за цією URL-адресою https://www.cs.toronto.edu/~kriz/cifar.html і розпакувати їх. Папка for-10-batches-py містить п’ять пакетів даних із 10000 XNUMX зображень кожен у довільному порядку.
Перш ніж створювати та навчати свою модель, потрібно застосувати певну обробку даних. Ви будете діяти наступним чином:
- Імпортуйте дані
- Перетворіть дані в чорно-білий формат
- Додайте всі партії
- Створіть навчальний набір даних
- Створіть візуалізатор зображень
Попередня обробка зображення
Крок 1) Імпортуйте дані
Згідно з офіційним веб-сайтом, ви можете завантажити дані за допомогою наступного коду. Код Autoencoder завантажить дані в словник разом із дані і етикетка. Зверніть увагу, що код є функцією.
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.
# 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 комп’ютер, шлях може бути ім’я файлу = '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 аргументи:
- зображення: вхід
- Форма: список, розмір зображення
- Cmap: виберіть колірну карту. За замовчуванням сірий
Ви можете спробувати побудувати перше зображення в наборі даних. Ви повинні побачити людину на коні.
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]: встановіть значення None, оскільки кількість каналів зображень у мережі дорівнює розміру пакету.
для отримання додаткової інформації зверніться до підручника на лінійна регресія.
Після цього вам потрібно створити ітератор. Без цього рядка коду жодні дані не проходитимуть через конвеєр.
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 нейронами. Блок декодера симетричний до кодера. Ви можете візуалізувати мережу на малюнку нижче. Зауважте, що ви можете змінити значення прихованого та центрального шарів.
Створення автокодувальника дуже схоже на будь-яку іншу модель глибокого навчання.
Ви побудуєте модель, дотримуючись таких кроків:
- Визначте параметри
- Визначте шари
- Визначте архітектуру
- Визначте оптимізацію
- Запустіть модель
- Оцініть модель
У попередньому розділі ви дізналися, як створити конвеєр для подачі моделі, тому немає потреби знову створювати набір даних. Ви побудуєте автокодер із чотирма шарами. Ви використовуєте ініціалізацію Xavier. Це метод встановлення початкових ваг рівних дисперсії вхідних і вихідних даних. Нарешті, ви використовуєте функцію активації elu. Ви регулюєте функцію втрат за допомогою регуляризатора L2.
Крок 1) Визначте параметри
Перший крок передбачає визначення кількості нейронів у кожному шарі, швидкості навчання та гіперпараметра регуляризатора.
Перед цим ви імпортуєте функцію частково. Це кращий метод для визначення параметрів щільних шарів. Наведений нижче код визначає значення архітектури автокодувальника. Як було зазначено раніше, автокодер має два шари, з 300 нейронами на перших шарах і 150 на других шарах. Їх значення зберігаються в n_hidden_1 і n_hidden_2.
Потрібно визначити швидкість навчання та гіперпараметр L2. Значення зберігаються в learn_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 з contrib оцінювача. У тому самому оцінювачі ви можете додати регуляризатор за допомогою 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) Визначте шари
Задані всі параметри щільних шарів; ви можете запакувати все в змінну dense_layer, використовуючи частковий об’єкт. dense_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. Вихід стає входом наступного шару, тому ви використовуєте його для обчислення hidden_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))
Потім вам потрібно оптимізувати функцію втрат. Ви використовуєте оптимізатор Adam для обчислення градієнтів. Цільова функція полягає в мінімізації втрат.
## 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, 1024
- Подайте на модель невидиме зображення, закодуйте/декодуйте зображення
- Роздрукуйте реальне та реконструйоване зображення
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
dense_layer(): зробити множення матриці
loss = tf.reduce_mean(tf.square(outputs - features)) optimizer = tf.train.AdamOptimizer(learning_rate) train = optimizer.minimize(loss)