"Это пятый день моего участия в ноябрьском испытании обновлений, ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Изучение скрытых переменных с помощью автоэнкодеров
Поскольку в многомерном входном пространстве много избыточности, которую можно сжать в некоторые низкоразмерные переменные, автоэнкодеры были впервые представлены в 1980-х годах Джеффри Хинтоном и др. Методы, используемые в традиционных методах машинного обучения для уменьшения размерности входных данных, включая анализ основных компонентов (PCA). Однако при создании изображений мы также хотим уменьшить пространство низкой размерности до пространства высокой размерности. Думайте об этом как о сжатии изображения, когда исходное изображение сжимается в формат файла, такой как JPEG, который меньше по размеру и его легче хранить и передавать. Затем компьютер может восстановить исходные пиксели JPEG. Другими словами, необработанные пиксели сжимаются в низкоразмерный формат JPEG и восстанавливаются до высокоразмерных необработанных пикселей для отображения.
Автоэнкодер — это неконтролируемый метод машинного обучения, который не требует обучающих меток для обучения модели. Однако, поскольку нам нужно использовать сами изображения в качестве меток, некоторые называют это машинным обучением с самоконтролем (auto
означает на латыниself
).
Основными строительными блоками автоэнкодера являются кодер и декодер. Кодер отвечает за преобразование многомерных входных данных в некоторые низкоразмерные латентные (скрытые) переменные. Декодер — это модуль, который преобразует скрытые переменные обратно в многомерное пространство.编码器-解码器
Архитектура также используется в других задачах машинного обучения, таких как семантическая сегментация, где нейронные сети сначала изучают представления изображений, а затем генерируют метки на уровне пикселей. На следующем рисунке показана общая архитектура автоэнкодера:
Вход и выход — это изображения одной размерности,z
— низкоразмерный скрытый вектор. Кодер сжимает ввод доz
, декодер будет обрабатывать обратное для создания выходного изображения.
Кодер
Кодировщик состоит из нескольких слоев нейронной сети, и мы создадим кодировщик, используя набор данных MNIST, который принимает входные данные размером 28x28x1. Нам нужно задать размерность скрытой переменной, здесь используется одномерный вектор. Размер скрытых переменных должен быть меньше размера входных данных. Это гиперпараметр, сначала попробуйте 10, который имеет степень сжатия 28 * 28/10 = 78,4.
Эта топология сети позволяет модели изучать важные сведения и отбрасывать менее важные функции слой за слоем, в результате чего получаются 10 наиболее важных функций. Это очень похоже на классификацию CNN, где размер карт признаков постепенно уменьшается сверху вниз.
Построение кодировщика с использованием сверточных слоев, предыдущийCNN
(НапримерVGG
) с использованием максимального пула для понижения дискретизации карты объектов, но новые сети, как правило, делают это, используя свертки с шагом 2 в сверточных слоях.
Мы будем следовать соглашению и назовем скрытую переменную z:
def Encoder(z_dim):
inputs = layers.Input(shape=[28,28,1])
x = inputs
x = Conv2D(filters=8, kernel_size=(3,3), strides=2, padding='same', activation='relu')(x)
x = Conv2D(filters=8, kernel_size=(3,3), strides=1, padding='same', activation='relu')(x)
x = Conv2D(filters=8, kernel_size=(3,3), strides=2, padding='same', activation='relu')(x)
x = Conv2D(filters=8, kernel_size=(3,3), strides=1, padding='same', activation='relu')(x)
x = Flatten()(x)
out = Dense(z_dim, activation='relu')(x)
return Model(inputs=inputs, outputs=out, name='encoder')
в типичномCNN
В архитектуре количество фильтров увеличивается, а размер карт объектов уменьшается. Однако наша цель — уменьшить размер функции, чтобы количество фильтров оставалось прежним, что полезно для таких вещей, какMNIST
Простые данные, такие как . Наконец, мы сглаживаем выходные данные последнего сверточного слоя и передаем их в плотный слой для вывода скрытых переменных.
декодер
Работа декодера по существу противоположна кодировщику, который преобразует скрытые переменные низкой размерности в выходные данные высокой размерности для аппроксимации входного изображения. Здесь карта признаков увеличена с 7x7 до 28x28 с использованием сверточных слоев в декодере:
def Decoder(z_dim):
inputs = layers.Input(shape=[z_dim])
x = inputs
x = Dense(7*7*64, activation='relu')(x)
x = Reshape((7,7,64))(x)
x = Conv2D(filters=64, kernel_size=(3,3), strides=1, padding='same', activation='relu')(x)
x = UpSampling2D((2,2))(x)
x = Conv2D(filters=32, kernel_size=(3,3), strides=1, padding='same', activation='relu')(x)
x = UpSampling2D((2,2))(x)
x = Conv2D(filters=32, kernel_size=(3,3), strides=2, padding='same', activation='relu')(x)
out = Conv2(filters=1, kernel_size=(3,3), strides=1, padding='same', activation='sigmoid')(x)
return Model(inputs=inputs, outputs=out, name='decoder')
В отличие от энкодера, целью декодера не является уменьшение размера, поэтому мы должны использовать больше фильтров, чтобы придать ему более мощную генеративную мощность.
UpSampling2D
Пиксели интерполируются для увеличения разрешения. Это аффинное преобразование (линейное умножение и сложение), поэтому возможно обратное распространение, но оно использует фиксированные веса и поэтому не поддается обучению. Другой популярный метод повышения дискретизации — использование транспонированного сверточного слоя, который поддается обучению, но может создать в сгенерированном изображении что-то вродеАртефакт шахматной доски.
Поэтому последние модели генерации изображений часто не используют транспонированные свертки:
Создайте автоэнкодер
Соедините кодировщик и декодер вместе, чтобы создать автокодировщик. Во-первых, мы отдельно создаем кодировщик и декодер. Затем мы передаем выходные данные кодировщика на вход декодера и создаем экземпляр модели с входными данными кодировщика и выходными данными декодера:
z_dim = 10
encoder = Encoder(z_dim)
decoder = Decoder(z_dim)
model_input = encoder.input
model_output = decoder(encoder.output)
autoencoder = Model(model_input, model_output)
Для обучения используется потеря L2, которая достигается путем сравнения каждого пикселя между выходным и ожидаемым результатом с помощью среднеквадратичной ошибки (MSE). В этом примере добавлены некоторые функции обратного вызова, которые будут вызываться после каждой эпохи обучения:
- ModelCheckpoint(monitor='val_loss') используется для сохранения модели, если текущая потеря проверки ниже, чем в предыдущую эпоху.
- EarlyStopping(monitor='val_loss', терпение = 10) может остановить обучение раньше, если потеря проверки не улучшится в течение 10 эпох.
Сгенерированное изображение следующим образом:
Создание изображений из скрытых переменных
Итак, какая польза от автоэнкодеров? Одним из применений автоэнкодеров является шумоподавление изображения, то есть добавление некоторого шума к входному изображению и обучение модели для создания четких изображений.
Если вы заинтересованы в использовании автоэнкодера для создания изображений, вы можете игнорировать кодировщик и просто использовать декодер для выборки из скрытых переменных для создания изображения. Первая проблема, с которой мы столкнулись, заключалась в том, чтобы определить, как делать выборку из скрытых переменных.
Для иллюстрации обучите другой автоэнкодер с z_dim = 2, чтобы мы могли исследовать скрытое пространство в двух измерениях:
График создается путем передачи 1000 выборок в обученный кодировщик и нанесения двух скрытых переменных на диаграмму рассеяния. Цветная полоса справа указывает силу числовых меток. Мы можем наблюдать из рисунка:
Категории скрытых переменных распределены неравномерно. Кластеры, которые полностью отделены от других категорий, можно увидеть в верхнем левом и верхнем правом углу. Однако категории в центре графика, как правило, располагаются более плотно и перекрывают друг друга.
На изображении ниже эти изображения генерируются путем взятия интервалов 1,0 в диапазоне скрытых переменных [-5, +5]:
Мы видим, что числа 0 и 1 хорошо представлены в выборочном распределении, хорошо нарисованном. Но цифры в середине нечеткие, и даже некоторые цифры отсутствуют в выборке.
мы также можем.ipynb
Добавьте элементы управления в код, которые позволяют менять скрытые переменные смахиванием для интерактивного создания изображений.