6 votos

El autocodificador no funciona (no puede aprender las características)

Soy completamente nuevo en el aprendizaje automático y estoy jugando con el paquete theanets. Lo que actualmente estoy tratando de hacer es conseguir un Autoencoder para reproducir una serie de distribuciones gaussianas:

def gen_inputs(x=28, sigma=2.0):
    target = np.array([skimage.filters.gaussian_filter(i, sigma) 
                for i in ((np.eye(x*x)*2)).reshape(x, x, x*x).transpose()]).reshape(x*x, x*x)
    return target

Luego intenté utilizar un Autoencoder (28*28, 9, 28*28) para entrenarlo. Los parámetros fueron los siguientes:

  • learning_rate = 0.01
  • input_noise = 0.01
  • Utilicé el SGD con la función de activación sigmoidea, junto con la función de salida lineal.

Pero mi red no pudo reproducir la entrada. Parece que siempre converge a una distribución media de pesos, lo que da lugar a resultados similares al ruido aleatorio. La función de pérdida (MSE) converge como debería. Aquí están los resultados:

enter image description here

2voto

lmjohns3 Puntos 579

(Autor principal de theanets aquí). Como se insinúa en los comentarios de tu pregunta, ¡este es realmente un problema de aprendizaje difícil! La red está, como indica el valor de pérdida optimizado durante el entrenamiento, aprendiendo los filtros óptimos para representar este conjunto de datos de entrada lo mejor posible.

Lo importante es pensar que los pesos de la red se ajustan para representar todo el espacio de entradas, no sólo una entrada. Supongo que esperas que la red aprenda una característica de mancha gaussiana, pero no es así como funciona.

Desde el punto de vista de la red, se le pide que represente una entrada muestreada de este conjunto de datos de forma arbitraria. ¿Qué píxeles de la siguiente muestra serán cero? ¿Cuáles serán distintos de cero? La red no lo sabe, porque las entradas cubren todo el espacio de píxeles con píxeles cero y no cero. La mejor representación para un conjunto de datos que llena el espacio de manera uniforme es un montón de valores pequeños distribuidos más o menos uniformemente, que es lo que se ve.

En comparación, intente limitar sus datos de entrada a un subconjunto de las manchas gaussianas. Pongámoslas todas en una franja diagonal de píxeles, por ejemplo:

import climate
import matplotlib.pyplot as plt
import numpy as np
import skimage.filters
import theanets

climate.enable_default_logging()

def gen_inputs(x=28, sigma=2.0):
    return np.array([
        skimage.filters.gaussian_filter(i, sigma).astype('f')
        for i in (np.eye(x*x)*2).reshape(x, x, x*x).transpose()
    ]).reshape(x*x, x*x)[10::27]

data = gen_inputs()

plt.imshow(data.mean(axis=0).reshape((28, 28)))
plt.show()

net = theanets.Autoencoder([784, 9, 784])
net.train(data, weight_l2=0.0001)

w = net.find('hid1', 'w').get_value().T
img = np.zeros((3 * 28, 3 * 28), float)
for r in range(3):
    for c in range(3):
        img[r*28:(r+1)*28, c*28:(c+1)*28] = w[r*3+c].reshape((28, 28))
plt.imshow(img)
plt.show()

Aquí hay un gráfico de los datos medios (el primer imshow en el código): data mean

Y aquí hay un gráfico de las características aprendidas (el segundo imshow ): learned features

Las características responden a la media de todo el conjunto de datos.

Si quieres que la red aprenda más características "individuales", puede ser bastante complicado. Cosas con las que puedes jugar:

  • Aumenta el número de unidades ocultas, como se sugiere en los comentarios.
  • Pruebe a entrenar con una penalización L1 sobre las activaciones de las unidades ocultas ( hidden_l1=0.5 ).
  • Intenta forzar que los pesos sean dispersos ( weight_l1=0.5 ).

Buena suerte.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X