Definicion de un Autoencoder

Como primer ejecricio se hara un autoencoder que codifique la entrada en menores dimensiones (encode) y luego reconstruya esa entrada (decode) para que la red de como salida la propia entrada.


In [ ]:
import tensorflow as tf
import numpy as np

class Autoencoder:
    def __init__(self, input_dim, hidden_dim, epoch=250, learning_rate=0.001):
        self.epoch = epoch # Numero de ciclos para aprender
        self.learning_rate = learning_rate #Hiper parametro para el optimizador (RMSProppOptimizer en este caso)
        # Capa de entrada (Input X que es el Dataset). shape=[None,input_dim] significa que en vez de None puede haber cualquier numero ahi (para poder hacer batch)
        x = tf.placeholder(dtype=tf.float32, shape=[None, input_dim])
        # Definir variables y operador del encoder (Del Input a la Hidden Layer)
        with tf.name_scope('encode'):
            weights = tf.Variable(tf.random_normal([input_dim, hidden_dim], dtype=tf.float32), name='weights')
            biases = tf.Variable(tf.zeros([hidden_dim]), name='biases')
            encoded = tf.nn.tanh(tf.matmul(x,weights) + biases)
        # Definir variables y operador del decoder (De la Hidden Layer al Output)    
        with tf.name_scope('decode'):
            weights = tf.Variable(tf.random_normal([hidden_dim, input_dim], dtype=tf.float32), name='weights')
            biases = tf.Variable(tf.zeros([hidden_dim]), name='biases')
            decoded = tf.nn.tanh(tf.matmul(encoded,weights) + biases)
        # Asignar a variables de la clase para que otro metodos de ella las puedan usar
        self.x = x
        self.encoded = encoded
        self.decoded = decoded
        # Funcion de costo (diferencia entre el output del autoencoder y el output esperado 
        # que en este caso es el propio input)
        self.loss = tf.sqrt(tf.reduce_mean(tf.square(tf.subtract(self.x,self.decoded))))
        # Definir el optimizador a utilizar y salvar los parametros que se iran aprendiendo en cada epoch
        self.train_op = tf.train.RMSPropOptimizer(self.learning_rate).minimize(self.loss)
        self.saver = tf.train.Saver()
        
    def train(self, data):
        num_samples = len(data)
        with tf.Session() as sess:
            sess.run(tf.global_variables_initializer())
            for i in range(self.epoch):
                for j in range(num_samples): # Entrenat la red sample por sample durante i epoch's
                    l, _ = sess.run([self.loss, self.train_op], feed_dict={self.x: [data[j]]})
                if i%10==0: # Solo imprimir como va la red cada 10 iteraciones (Vigilar como desciende el error!)
                    print("Epoch {}: loss = {}".format(i,l))
                    self.saver.save(sess, './checkpoints/autoencoder_model.ckpt')

    def test(self, data): #Data es un solo ejemplo (nunca antes visto) que entrara a la red y esta dara el resultado (que debe de ser el propio input si se entreno correctamente)
        with tf.Session() as sess:
            self.saver.restore(sess, './checkpoints/autoencoder_model.ckpt')
            hidden,reconstructed = sess.run([self.encoded, self.decoded], feed_dict={self.x: data})
        print('input', data)
        print('compressed',hidden)
        print('reconstructed',reconstructed)
        return reconstructed

Ejecutar el autoencoder


In [ ]:
from sklearn import datasets

hidden_dim = 1
data = datasets.load_iris().data
input_dim = len(data[0])
ae = Autoencoder(input_dim, hidden_dim,epoch=500)
ae.train(data)
ae.test([[ 5.0 ,3.9,  2.4,  1.2]])

Aplicando a Imagenes

1) Leer el dataset 2) Convertir a escala de grises 3) Aplicar el Autoencoder


In [ ]:
import pickle
import numpy as np

def unpickle(file):
    fo = open(file,'rb')
    img_dict = pickle.load(fo, encoding='latin1')
    fo.close()
    return img_dict

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

names = unpickle('./cifar-10-batches-py/batches.meta')['label_names']
data, labels = [],[]
for i in range(1,6):
    filename = './cifar-10-batches-py/data_batch_' + str(i)
    batch_data = unpickle(filename)
    if len(data) > 0:
        data = np.vstack((data, batch_data['data']))
        labels = np.hstack((labels, batch_data['labels']))
    else:
        data = batch_data['data']
        labels = batch_data['labels']

data = grayscale(data)

x = np.matrix(data)
y = np.array(labels)

horse_indices = np.where(y == 7)[0]

horse_x = x[horse_indices]

print(np.shape(horse_x))

input_dim = np.shape(horse_x)[1]
hidden_dim = 100
ae = Autoencoder(input_dim, hidden_dim)
ae.train(horse_x)