Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/tutorials/generative/autoencoder.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Introdução aos autoencoders

Este tutorial apresenta os autoencoders com três exemplos: os básicos, a remoção de ruído de imagem e a detecção de anomalias.

O autoencoder é um tipo especial de rede neural, treinada para copiar sua entrada para a saída. Por exemplo, dada a imagem de um dígito escrito à mão, um autoencoder primeiro codifica a imagem em uma representação latente de menor dimensão, depois decodifica a representação latente em uma imagem. O autoencoder aprende a comprimir os dados ao mesmo tempo em que minimiza o erro de reconstrução.

Para saber mais sobre autoencoders, você pode ler o capítulo 14 do livro Deep Learning (Aprendizado profundo, em tradução livre), escrito por Ian Goodfellow, Yoshua Bengio e Aaron Courville.

Importar o TensorFlow e outras bibliotecas

import matplotlib.pyplot as plt import numpy as np import pandas as pd import tensorflow as tf from sklearn.metrics import accuracy_score, precision_score, recall_score from sklearn.model_selection import train_test_split from tensorflow.keras import layers, losses from tensorflow.keras.datasets import fashion_mnist from tensorflow.keras.models import Model

Carregar o dataset

Para começar, você treinará o autoencoder básico usando o dataset Fashion MNIST. Cada imagem desse dataset tem 28x28 pixels.

(x_train, _), (x_test, _) = fashion_mnist.load_data() x_train = x_train.astype('float32') / 255. x_test = x_test.astype('float32') / 255. print (x_train.shape) print (x_test.shape)

Primeiro exemplo: autoencoder básico

Resultados do autoencoder básico

Defina um autoencoder com duas camadas Dense: um encoder, que comprime as imagens em um vetor latente de 64 dimensões, e um decoder, que reconstrói a imagem original a partir do espaço latente.

Para definir o modelo, use a API de subclasses do modelo do Keras.

class Autoencoder(Model): def __init__(self, latent_dim, shape): super(Autoencoder, self).__init__() self.latent_dim = latent_dim self.shape = shape self.encoder = tf.keras.Sequential([ layers.Flatten(), layers.Dense(latent_dim, activation='relu'), ]) self.decoder = tf.keras.Sequential([ layers.Dense(tf.math.reduce_prod(shape), activation='sigmoid'), layers.Reshape(shape) ]) def call(self, x): encoded = self.encoder(x) decoded = self.decoder(encoded) return decoded shape = x_test.shape[1:] latent_dim = 64 autoencoder = Autoencoder(latent_dim, shape)
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())

Treine o modelo usando x_train como a entrada e o alvo. O encoder aprenderá a comprimir o dataset de 784 dimensões para o espaço latente, e o decoder aprenderá a reconstruir as imagens originais.

autoencoder.fit(x_train, x_train, epochs=10, shuffle=True, validation_data=(x_test, x_test))

Agora que o modelo está treinado, vamos testá-lo fazendo a codificação e a decodificação de imagens do conjunto de teste.

encoded_imgs = autoencoder.encoder(x_test).numpy() decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
n = 10 plt.figure(figsize=(20, 4)) for i in range(n): # display original ax = plt.subplot(2, n, i + 1) plt.imshow(x_test[i]) plt.title("original") plt.gray() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) # display reconstruction ax = plt.subplot(2, n, i + 1 + n) plt.imshow(decoded_imgs[i]) plt.title("reconstructed") plt.gray() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) plt.show()

Segundo exemplo: remoção de ruído de imagem

Resultados da remoção de ruído de imagem

Um autoencoder também pode ser treinado para remover ruído das imagens. Na próxima seção, você criará uma versão do dataset Fashion MNIST com ruído aplicando ruído aleatório a cada imagem. Depois, você treinará um autoencoder usando a imagem com ruído como entrada e a imagem original como alvo.

Vamos importar o dataset novamente para omitir as modificações feitas anteriormente.

(x_train, _), (x_test, _) = fashion_mnist.load_data()
x_train = x_train.astype('float32') / 255. x_test = x_test.astype('float32') / 255. x_train = x_train[..., tf.newaxis] x_test = x_test[..., tf.newaxis] print(x_train.shape)

Adição de ruído aleatório às imagens

noise_factor = 0.2 x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape) x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.) x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)

Plote as imagens com ruído.

n = 10 plt.figure(figsize=(20, 2)) for i in range(n): ax = plt.subplot(1, n, i + 1) plt.title("original + noise") plt.imshow(tf.squeeze(x_test_noisy[i])) plt.gray() plt.show()

Definir um autoencoder convolucional

Neste exemplo, você treinará um autoencoder convolucional usando camadas Conv2D no encoder e camadas Conv2DTranspose no decoder.

class Denoise(Model): def __init__(self): super(Denoise, self).__init__() self.encoder = tf.keras.Sequential([ layers.Input(shape=(28, 28, 1)), layers.Conv2D(16, (3, 3), activation='relu', padding='same', strides=2), layers.Conv2D(8, (3, 3), activation='relu', padding='same', strides=2)]) self.decoder = tf.keras.Sequential([ layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'), layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'), layers.Conv2D(1, kernel_size=(3, 3), activation='sigmoid', padding='same')]) def call(self, x): encoded = self.encoder(x) decoded = self.decoder(encoded) return decoded autoencoder = Denoise()
autoencoder.compile(optimizer='adam', loss=losses.MeanSquaredError())
autoencoder.fit(x_train_noisy, x_train, epochs=10, shuffle=True, validation_data=(x_test_noisy, x_test))

Vamos conferir o resumo do encoder. Observe como as imagens são reduzidas de 28x28 para 7x7 pixels.

autoencoder.encoder.summary()

O decoder amplia as imagens de 7x7 para 28x28 pixels.

autoencoder.decoder.summary()

Vamos plotar tanto as imagens com ruído quanto as imagens sem ruído produzidas pelo autoencoder.

encoded_imgs = autoencoder.encoder(x_test_noisy).numpy() decoded_imgs = autoencoder.decoder(encoded_imgs).numpy()
n = 10 plt.figure(figsize=(20, 4)) for i in range(n): # display original + noise ax = plt.subplot(2, n, i + 1) plt.title("original + noise") plt.imshow(tf.squeeze(x_test_noisy[i])) plt.gray() ax.get_xaxis().set_visible(False) ax.get_yaxis().set_visible(False) # display reconstruction bx = plt.subplot(2, n, i + n + 1) plt.title("reconstructed") plt.imshow(tf.squeeze(decoded_imgs[i])) plt.gray() bx.get_xaxis().set_visible(False) bx.get_yaxis().set_visible(False) plt.show()

Terceiro exemplo: detecção de anomalias

Visão geral

Neste exemplo, você treinará um autoencoder para detectar anomalias no dataset ECG5000. Este dataset contém 5.000 eletrocardiogramas, cada um com 140 pontos de dados. Você usará uma versão simplificada do dataset, em que cada exemplo foi rotulado como 0 (correspondente a um ritmo cardíaco anormal) ou 1 (correspondente a um ritmo cardíaco normal). O seu interesse é identificar os ritmos anormais.

Observação: este é um dataset rotulado, então podemos dizer que é um exemplo de aprendizado supervisionado. O objeto deste exemplo é ilustrar os conceitos de detecção de anomalias que você pode aplicar a datasets maiores, quando não tiver rótulos disponíveis (por exemplo, se você tivesse milhares de ritmos normais e somente um pequeno número de ritmos anormais).

Como detectar anomalias usando um autoencoder? Lembre-se de que o autoencoder é treinado para minimizar erros de reconstrução. Você treinará um autoencoder usando somente os ritmos normais e depois o utilizará para reconstruir todos os dados. Nossa hipótese é que os ritmos anormais terão um erro de reconstrução maior. Em seguida, você classificará um ritmo como uma anomalia se o erro de reconstrução ultrapassar um limite estabelecido.

Carregar os dados de eletrocardiogramas

O dataset que você usará é baseado no de timeseriesclassification.com.

# Download the dataset dataframe = pd.read_csv('http://storage.googleapis.com/download.tensorflow.org/data/ecg.csv', header=None) raw_data = dataframe.values dataframe.head()
# The last element contains the labels labels = raw_data[:, -1] # The other data points are the electrocadriogram data data = raw_data[:, 0:-1] train_data, test_data, train_labels, test_labels = train_test_split( data, labels, test_size=0.2, random_state=21 )

Normalize os dados como [0,1].

min_val = tf.reduce_min(train_data) max_val = tf.reduce_max(train_data) train_data = (train_data - min_val) / (max_val - min_val) test_data = (test_data - min_val) / (max_val - min_val) train_data = tf.cast(train_data, tf.float32) test_data = tf.cast(test_data, tf.float32)

Você treinará o autoencoder usando somente os ritmos normais, que são rotulados como 1 neste dataset. Separe os ritmos normais dos anormais.

train_labels = train_labels.astype(bool) test_labels = test_labels.astype(bool) normal_train_data = train_data[train_labels] normal_test_data = test_data[test_labels] anomalous_train_data = train_data[~train_labels] anomalous_test_data = test_data[~test_labels]

Plote um eletrocardiograma normal.

plt.grid() plt.plot(np.arange(140), normal_train_data[0]) plt.title("A Normal ECG") plt.show()

Plote um eletrocardiograma anômalo.

plt.grid() plt.plot(np.arange(140), anomalous_train_data[0]) plt.title("An Anomalous ECG") plt.show()

Criação do modelo

class AnomalyDetector(Model): def __init__(self): super(AnomalyDetector, self).__init__() self.encoder = tf.keras.Sequential([ layers.Dense(32, activation="relu"), layers.Dense(16, activation="relu"), layers.Dense(8, activation="relu")]) self.decoder = tf.keras.Sequential([ layers.Dense(16, activation="relu"), layers.Dense(32, activation="relu"), layers.Dense(140, activation="sigmoid")]) def call(self, x): encoded = self.encoder(x) decoded = self.decoder(encoded) return decoded autoencoder = AnomalyDetector()
autoencoder.compile(optimizer='adam', loss='mae')

O autoencoder é treinado usando-se somente os eletrocardiogramas normais, mas é avaliado usando-se o conjunto de teste completo.

history = autoencoder.fit(normal_train_data, normal_train_data, epochs=20, batch_size=512, validation_data=(test_data, test_data), shuffle=True)
plt.plot(history.history["loss"], label="Training Loss") plt.plot(history.history["val_loss"], label="Validation Loss") plt.legend()

Em breve, você classificará um eletrocardiograma como anômalo se o erro de reconstrução for maior do que um desvio padrão dos exemplos de treinamento normais. Primeiro, vamos plotar um eletrocardiograma normal do conjunto de treinamento, a reconstrução após a codificação e decodificação pelo autoencoder e o erro de reconstrução.

encoded_data = autoencoder.encoder(normal_test_data).numpy() decoded_data = autoencoder.decoder(encoded_data).numpy() plt.plot(normal_test_data[0], 'b') plt.plot(decoded_data[0], 'r') plt.fill_between(np.arange(140), decoded_data[0], normal_test_data[0], color='lightcoral') plt.legend(labels=["Input", "Reconstruction", "Error"]) plt.show()

Crie um gráfico similar, desta vez para um exemplo de teste anômalo.

encoded_data = autoencoder.encoder(anomalous_test_data).numpy() decoded_data = autoencoder.decoder(encoded_data).numpy() plt.plot(anomalous_test_data[0], 'b') plt.plot(decoded_data[0], 'r') plt.fill_between(np.arange(140), decoded_data[0], anomalous_test_data[0], color='lightcoral') plt.legend(labels=["Input", "Reconstruction", "Error"]) plt.show()

Detecção de anomalias

Detecte anomalias calculando se a perda de reconstrução é maior do que um limite estabelecido. Neste tutorial, você calculará o erro médio para exemplos normais do conjunto de treinamento, depois classificará exemplos futuros como anômalos se o erro de reconstrução for maior do que um desvio padrão do conjunto de treinamento.

Plotar o erro de reconstrução em eletrocardiogramas normais do conjunto de treinamento

reconstructions = autoencoder.predict(normal_train_data) train_loss = tf.keras.losses.mae(reconstructions, normal_train_data) plt.hist(train_loss[None,:], bins=50) plt.xlabel("Train loss") plt.ylabel("No of examples") plt.show()

Escolha um valor de limite que seja um desvio padrão acima da média.

threshold = np.mean(train_loss) + np.std(train_loss) print("Threshold: ", threshold)

Observação: existem outras estratégias para selecionar um valor de limite acima do qual os exemplos do teste devem ser classificados como anômalos. A estratégia mais adequada dependerá do dataset. Confira os links no final deste tutorial para saber mais.

Se você avaliar o erro de reconstrução dos exemplos anômalos no conjunto de teste, notará que a maioria tem um erro de reconstrução maior do que o limite. Você pode variar o limite para ajustar a precisão e o recall do classificador.

reconstructions = autoencoder.predict(anomalous_test_data) test_loss = tf.keras.losses.mae(reconstructions, anomalous_test_data) plt.hist(test_loss[None, :], bins=50) plt.xlabel("Test loss") plt.ylabel("No of examples") plt.show()

Classifique um eletrocardiograma como uma anomalia se o erro de reconstrução for maior do que o limite.

def predict(model, data, threshold): reconstructions = model(data) loss = tf.keras.losses.mae(reconstructions, data) return tf.math.less(loss, threshold) def print_stats(predictions, labels): print("Accuracy = {}".format(accuracy_score(labels, predictions))) print("Precision = {}".format(precision_score(labels, predictions))) print("Recall = {}".format(recall_score(labels, predictions)))
preds = predict(autoencoder, test_data, threshold) print_stats(preds, test_labels)

Próximos passos

Para saber mais sobre a detecção de anomalias com autoencoders, confira este excelente exemplo interativo criado com o TensorFlow.js por Victor Dibia. Para um caso de uso real, veja como a Airbus detecta anomalias nos dados de telemetria da ISS usando o TensorFlow. Para saber mais sobre as noções básicas, leia esta postagem de blog de François Chollet. Se quiser saber mais detalhes, confira o capítulo 14 do livro Deep Learning (Aprendizado profundo, em tradução livre), escrito por Ian Goodfellow, Yoshua Bengio e Aaron Courville.