(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):
Y aquí hay un gráfico de las características aprendidas (el segundo imshow
):
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.