O que é um Autoencoder?
Um Autoencoder é uma ferramenta para aprender a codificação de dados de maneira eficiente e não supervisionada. É um tipo de rede neural artificial que ajuda você a aprender a representação de conjuntos de dados para redução de dimensionalidade, treinando a rede neural para ignorar o ruído do sinal. É uma ótima ferramenta para recriar uma entrada.
Em palavras simples, a máquina tira, digamos, uma imagem e pode produzir uma imagem intimamente relacionada. A entrada neste tipo de rede neural não está marcada, o que significa que a rede é capaz de aprender sem supervisão. Mais precisamente, a entrada é codificada pela rede para se concentrar apenas no recurso mais crítico. Esta é uma das razões pelas quais o autoencoder é popular para redução de dimensionalidade. Além disso, os autoencoders podem ser usados para produzir modelos de aprendizagem generativos . Por exemplo, a rede neural pode ser treinada com um conjunto de faces e então pode produzir novas faces.
Neste tutorial do TensorFlow Autoencoder, você aprenderá:
- O que é um Autoencoder?
- Como funciona o Autoencoder?
- Exemplo de codificador automático empilhado
- Construir um Autoencoder com TensorFlow
- Pré-processamento de imagem
- Definir Estimador de Conjunto de Dados
- Construa a rede
Como funciona o Autoencoder?
O objetivo de um autencoder é produzir uma aproximação da entrada focando apenas nos recursos essenciais. Você pode pensar por que não apenas aprender como copiar e colar a entrada para produzir a saída. Na verdade, um autoencoder é um conjunto de restrições que força a rede a aprender novas maneiras de representar os dados, diferentes de simplesmente copiar a saída.
Um autencoder típico é definido com uma entrada, uma representação interna e uma saída (uma aproximação da entrada). O aprendizado ocorre nas camadas vinculadas à representação interna. Na verdade, existem dois blocos principais de camadas que se parecem com uma rede neural tradicional. A ligeira diferença é que a camada que contém a saída deve ser igual à entrada. Na figura abaixo, a entrada original vai para o primeiro bloco denominado codificador . Esta representação interna comprime (reduz) o tamanho da entrada. No segundo bloco ocorre a reconstrução da entrada. Esta é a fase de decodificação.
O modelo atualizará os pesos minimizando a função de perda. O modelo é penalizado se a saída da reconstrução for diferente da entrada.
Concretamente, imagine uma imagem com tamanho 50x50 (ou seja, 250 pixels) e uma rede neural com apenas uma camada oculta composta por cem neurônios. O aprendizado é feito em um mapa de recursos que é duas vezes menor do que a entrada. Isso significa que a rede precisa encontrar uma maneira de reconstruir 250 pixels com apenas um vetor de neurônios igual a 100.
Exemplo de codificador automático empilhado
Neste tutorial do Autoencoder, você aprenderá como usar um autoencoder empilhado. A arquitetura é semelhante a uma rede neural tradicional. A entrada vai para uma camada oculta a fim de ser comprimida, ou diminuir seu tamanho, e então chega às camadas de reconstrução. O objetivo é produzir uma imagem de saída tão próxima quanto a original. O modelo tem que aprender uma maneira de cumprir sua tarefa sob um conjunto de restrições, ou seja, com uma dimensão inferior.
Hoje em dia, os Autoencoders em Deep Learning são usados principalmente para diminuir o ruído de uma imagem. Imagine uma imagem com arranhões; um humano ainda é capaz de reconhecer o conteúdo. A ideia do autencoder com eliminação de ruído é adicionar ruído à imagem para forçar a rede a aprender o padrão por trás dos dados.
A outra família útil do Autoencoder Deep Learning é o autoencoder variacional. Este tipo de rede pode gerar novas imagens. Imagine que você treina uma rede com a imagem de um homem; tal rede pode produzir novos rostos.
Construir um Autoencoder com TensorFlow
Neste tutorial, você aprenderá como construir um autoencoder empilhado para reconstruir uma imagem.
Você usará o conjunto de dados CIFAR-10 que contém 60.000 imagens de 32x32 cores. O conjunto de dados do Autoencoder já está dividido entre 50.000 imagens para treinamento e 10.000 para teste. Existem até dez classes:
- Avião
- Automóvel
- Pássaro
- Gato
- Cervo
- Cão
- Sapo
- Cavalo
- Enviar
- Caminhão
Você precisa baixar as imagens neste URL https://www.cs.toronto.edu/~kriz/cifar.html e descompactá-lo. A pasta for-10-batches-py contém cinco lotes de dados com 10.000 imagens cada em uma ordem aleatória.
Antes de construir e treinar seu modelo, você precisa aplicar algum processamento de dados. Você procederá da seguinte forma:
- Importar os dados
- Converta os dados para o formato preto e branco
- Anexar todos os lotes
- Construir o conjunto de dados de treinamento
- Construir um visualizador de imagens
Pré-processamento de imagem
Etapa 1) Importe os dados.
De acordo com o site oficial, você pode fazer o upload dos dados com o seguinte código. O código do Autoencoder carregará os dados em um dicionário com os dados e o rótulo . Observe que o código é uma função.
import numpy as npimport tensorflow as tfimport pickledef unpickle(file):import picklewith open(file, 'rb') as fo:dict = pickle.load(fo, encoding='latin1')return dict
Etapa 2) Converta os dados para o formato preto e branco
Para simplificar, você converterá os dados em tons de cinza. Ou seja, com apenas uma dimensão contra três para imagem em cores. A maior parte da rede neural funciona apenas com uma entrada de dimensão.
def grayscale(im):return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)
Etapa 3) Anexar todos os lotes
Agora que ambas as funções foram criadas e o conjunto de dados carregado, você pode escrever um loop para anexar os dados na memória. Se você verificar cuidadosamente, o arquivo descompactado com os dados é denominado data_batch_ com um número de 1 a 5. Você pode percorrer os arquivos e anexá-los aos dados.
Quando esta etapa é concluída, você converte os dados de cores em um formato de escala de cinza. Como você pode ver, a forma dos dados é 50000 e 1024. Os 32 * 32 pixels agora estão achatados para 2014.
# Load the data into memorydata, labels = [], []## Loop over the bfor 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)
Nota: Altere './cifar-10-batches-py/data_batch_' para a localização real do seu arquivo. Por exemplo, para máquina Windows, o caminho pode ser filename = 'E: \ cifar-10-batches-py \ data_batch_' + str (i)
Etapa 4) Construir o conjunto de dados de treinamento
Para tornar o treinamento mais rápido e fácil, você treinará um modelo apenas nas imagens do cavalo. Os cavalos são a sétima classe nos dados do rótulo. Conforme mencionado na documentação do conjunto de dados CIFAR-10, cada classe contém 5.000 imagens. Você pode imprimir a forma dos dados para confirmar que há 5.000 imagens com 1.024 colunas, conforme mostrado na etapa de exemplo do TensorFlow Autoencoder abaixo.
horse_i = np.where(y == 7)[0]horse_x = x[horse_i]print(np.shape(horse_x))(5000, 1024)
Etapa 5) Construir um visualizador de imagens
Finalmente, você constrói uma função para plotar as imagens. Você precisará desta função para imprimir a imagem reconstruída do codificador automático.
Uma maneira fácil de imprimir imagens é usar o objeto imshow da biblioteca matplotlib. Observe que você precisa converter a forma dos dados de 1024 para 32 * 32 (ou seja, formato de uma imagem).
# To plot pretty figures%matplotlib inlineimport matplotlibimport matplotlib.pyplot as pltdef plot_image(image, shape=[32, 32], cmap = "Greys_r"):plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest")plt.axis("off")
A função leva 3 argumentos:
- Imagem: a entrada
- Forma: lista, a dimensão da imagem
- Cmap: escolha o mapa de cores. Por padrão, cinza
Você pode tentar plotar a primeira imagem no conjunto de dados. Você deveria ver um homem em um cavalo.
plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")
Definir Estimador de Conjunto de Dados
Tudo bem, agora que o conjunto de dados está pronto para uso, você pode começar a usar o Tensorflow. Antes de construir o modelo, vamos usar o estimador de conjunto de dados do Tensorflow para alimentar a rede.
Você criará um conjunto de dados com o estimador TensorFlow. Para refrescar sua mente, você precisa usar:
- from_tensor_slices
- repita
- lote
O código completo para construir o conjunto de dados é:
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
Observe que x é um marcador de posição com a seguinte forma:
- [Nenhum, n_inputs]: Defina como Nenhum porque o número de alimentação de imagem para a rede é igual ao tamanho do lote.
para obter detalhes, consulte o tutorial sobre regressão linear.
Depois disso, você precisa criar o iterador. Sem essa linha de código, nenhum dado passará pelo pipeline.
iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()
Agora que o pipeline está pronto, você pode verificar se a primeira imagem é a mesma de antes (ou seja, um homem em um cavalo).
Você define o tamanho do lote como 1 porque deseja alimentar o conjunto de dados com apenas uma imagem. Você pode ver a dimensão dos dados com print (sess.run (features) .shape). É igual a (1, 1024). 1 significa que apenas uma imagem com 1024 é alimentada cada. Se o tamanho do lote for definido como dois, duas imagens passarão pelo pipeline. (Não altere o tamanho do lote. Caso contrário, ocorrerá um erro. Apenas uma imagem por vez pode ir para a função plot_image ().
## Parametersn_inputs = 32 * 32BATCH_SIZE = 1batch_size = tf.placeholder(tf.int64)# using a placeholderx = tf.placeholder(tf.float32, shape=[None,n_inputs])## Datasetdataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()## Print the imagewith tf.Session() as sess:# feed the placeholder with datasess.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)
Construa a rede
É hora de construir a rede. Você treinará um autoencoder empilhado, ou seja, uma rede com várias camadas ocultas.
Sua rede terá uma camada de entrada com 1024 pontos, ou seja, 32x32, o formato da imagem.
O bloco codificador terá uma camada superior oculta com 300 neurônios e uma camada central com 150 neurônios. O bloco do decodificador é simétrico ao codificador. Você pode visualizar a rede na imagem abaixo. Observe que você pode alterar os valores das camadas central e oculta.
Construir um autoencoder é muito semelhante a qualquer outro modelo de aprendizado profundo.
Você construirá o modelo seguindo estas etapas:
- Defina os parâmetros
- Defina as camadas
- Defina a arquitetura
- Defina a otimização
- Execute o modelo
- Avalie o modelo
Na seção anterior, você aprendeu como criar um pipeline para alimentar o modelo, portanto, não há necessidade de criar mais uma vez o conjunto de dados. Você construirá um autencoder com quatro camadas. Você usa a inicialização do Xavier. Esta é uma técnica para definir os pesos iniciais iguais à variância da entrada e da saída. Finalmente, você usa a função de ativação elu. Você regulariza a função de perda com o regularizador L2.
Etapa 1) Definir os parâmetros
A primeira etapa implica definir o número de neurônios em cada camada, a taxa de aprendizado e o hiperparâmetro do regularizador.
Antes disso, você importa a função parcialmente. É um método melhor para definir os parâmetros das camadas densas. O código a seguir define os valores da arquitetura do autencoder. Conforme listado antes, o autoencoder tem duas camadas, com 300 neurônios nas primeiras camadas e 150 nas segundas camadas. Seus valores são armazenados em n_hidden_1 e n_hidden_2.
Você precisa definir a taxa de aprendizagem e o hiperparâmetro L2. Os valores são armazenados em learning_rate e l2_reg
from functools import partial## Encodern_hidden_1 = 300n_hidden_2 = 150 # codings## Decodern_hidden_3 = n_hidden_1n_outputs = n_inputslearning_rate = 0.01l2_reg = 0.0001
A técnica de inicialização do Xavier é chamada com o objeto xavier_initializer do estimador contrib. No mesmo estimador, você pode adicionar o regularizador com l2_regularizer
## Define the Xavier initializationxav_init = tf.contrib.layers.xavier_initializer()## Define the L2 regularizerl2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)
Etapa 2) Definir as camadas
Todos os parâmetros das camadas densas foram definidos; você pode empacotar tudo na variável dense_layer usando o objeto parcial. dense_layer que usa a ativação ELU, inicialização Xavier e regularização L2.
## Create the dense layerdense_layer = partial(tf.layers.dense,activation=tf.nn.elu,kernel_initializer=xav_init,kernel_regularizer=l2_regularizer)
Etapa 3) Definir a arquitetura
Se você olhar a imagem da arquitetura, verá que a rede empilha três camadas com uma camada de saída. No código abaixo, você conecta as camadas apropriadas. Por exemplo, a primeira camada calcula o produto escalar entre os recursos da matriz de entrada e as matrizes contendo os 300 pesos. Depois que o produto escalar é calculado, a saída vai para a função de ativação Elu. A saída se torna a entrada da próxima camada, é por isso que você a usa para calcular hidden_2 e assim por diante. A multiplicação das matrizes é a mesma para cada camada porque você usa a mesma função de ativação. Observe que a última camada, saídas, não aplica uma função de ativação. Faz sentido porque esta é a entrada reconstruída
## Make the mat mulhidden_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)
Etapa 4) Definir a otimização
A última etapa é construir o otimizador. Você usa o erro quadrático médio como uma função de perda. Se você se lembra do tutorial sobre regressão linear, sabe que o MSE é calculado com a diferença entre a saída prevista e o rótulo real. Aqui, o rótulo é o recurso porque o modelo tenta reconstruir a entrada. Portanto, você quer a média da soma da diferença do quadrado entre a saída e a entrada previstas. Com o TensorFlow, você pode codificar a função de perda da seguinte maneira:
loss = tf.reduce_mean(tf.square(outputs - features))
Então, você precisa otimizar a função de perda. Você usa o otimizador Adam para calcular os gradientes. A função objetivo é minimizar a perda.
## Optimizeloss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)
Mais uma configuração antes de treinar o modelo. Você deseja usar um tamanho de lote de 150, ou seja, alimentar o pipeline com 150 imagens a cada iteração. Você precisa calcular o número de iterações manualmente. Isso é trivial:
Se você deseja passar 150 imagens a cada vez e sabe que há 5000 imagens no conjunto de dados, o número de iterações é igual a. Em python, você pode executar os seguintes códigos e garantir que a saída seja 33:
BATCH_SIZE = 150### Number of batches : length dataset / batch sizen_batches = horse_x.shape[0] // BATCH_SIZEprint(n_batches)33
Etapa 5) Execute o modelo
Por último, mas não menos importante, treine o modelo. Você está treinando o modelo com 100 épocas. Ou seja, o modelo verá 100 vezes as imagens para pesos otimizados.
Você já está familiarizado com os códigos para treinar um modelo no Tensorflow. A pequena diferença é canalizar os dados antes de executar o treinamento. Dessa forma, o modelo treina mais rápido.
Você está interessado em imprimir a perda após dez épocas para ver se o modelo está aprendendo algo (ou seja, a perda está diminuindo). O treinamento leva de 2 a 5 minutos, dependendo do hardware da sua máquina.
## Set paramsn_epochs = 100## Call Saver to save the model and re-use it later during evaluationsaver = tf.train.Saver()with tf.Session() as sess:sess.run(tf.global_variables_initializer())# initialise iterator with train datasess.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 shownprint("\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.45510 Train MSE: 1672.67620 Train MSE: 1514.70930 Train MSE: 1404.311840 Train MSE: 1425.05850 Train MSE: 1479.063160 Train MSE: 1609.525970 Train MSE: 1482.322380 Train MSE: 1445.703590 Train MSE: 1453.8597Model saved in path: ./model.ckpt
Etapa 6) Avalie o modelo
Agora que você treinou seu modelo, é hora de avaliá-lo. Você precisa importar o sert de teste do arquivo / 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'])
NOTA: Para uma máquina Windows, o código se torna test_data = unpickle (r "E: \ cifar-10-batches-py \ test_batch")
Você pode tentar imprimir as imagens 13, que é um cavalo
plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")
Para avaliar o modelo, você usará o valor de pixel desta imagem e verá se o codificador pode reconstruir a mesma imagem após encolher 1024 pixels. Observe que você define uma função para avaliar o modelo em diferentes imagens. O modelo deve funcionar melhor apenas em cavalos.
A função leva dois argumentos:
- df: Importar os dados de teste
- número_da_imagem: indica qual imagem importar
A função é dividida em três partes:
- Remodele a imagem para a dimensão correta, ou seja, 1, 1024
- Alimente o modelo com a imagem invisível, codifique / decodifique a imagem
- Imprima a imagem real e reconstruída
def reconstruct_image(df, image_number = 1):## Part 1: Reshape the image to the correct dimension i.e 1, 1024x_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 imagewith 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 imageoutputs_val = outputs.eval()print(outputs_val.shape)fig = plt.figure()# Plot realax1 = fig.add_subplot(121)plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")# Plot estimatedax2 = fig.add_subplot(122)plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r")plt.tight_layout()fig = plt.gcf()
Agora que a função de avaliação está definida, você pode dar uma olhada na imagem reconstruída número treze
reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckptModel restored.(1, 1024)
Resumo
O objetivo principal de um codificador automático é compactar os dados de entrada e, em seguida, descompactá-los em uma saída que se pareça com os dados originais.
A arquitetura de um autoencoder simétrico com uma camada pivô denominada camada central.
Você pode criar o codificador automático usando:
- Parcial: para criar as camadas densas com a configuração típica:
-
tf.layers.dense,activation=tf.nn.elu,kernel_initializer=xav_init,kernel_regularizer=l2_regularizer
- dense_layer (): para fazer a multiplicação da matriz
você pode definir a função de perda e otimização com:
loss = tf.reduce_mean(tf.square(outputs - features))optimizer = tf.train.AdamOptimizer(learning_rate)train = optimizer.minimize(loss)
A última execução de uma sessão para treinar o modelo.