5 votos

¿La red neuronal con capa oculta funciona peor que sin ella?

Estoy intentando entrenar un clasificador en un único vector de entrada de longitud 3000, e intentando predecir a cuál de las 30 clases pertenece cada vector de entrada.

Con 1M de ejemplos de entrada/salida etiquetados (dividir el 80% de entrenamiento, 20% de validación), puedo obtener cerca del 50% de precisión simplemente entrenando pesos en una matriz de 3000 por 30. En otras palabras, 50% de precisión sin una capa oculta.

Cuando añado una capa oculta con 100 neuronas, o 500, o 50, veo constantemente un rendimiento peor que en mi red sin capas ocultas. Espero que esto sea de alguna manera una función de mis hiperparámetros, pero he intentado ajustar la tasa de aprendizaje y el tamaño del lote a través de un amplio rango de valores. También he intentado salidas sigmoidales, tanh y relu en la capa oculta.

No importa lo que intente, no veo más de un 20% de precisión cuando añado una capa oculta.

Feliz de proporcionar más detalles según sea necesario, pero básicamente estoy buscando consejo sobre cómo depurar (estoy usando esto como una excusa para explorar Tensorflow.) Esperaría que mi red con una capa oculta debería al menos tan bien como sin ella.


Ejemplo de código

Así es como estoy entrenando a la modelo (note que también he intentado sigmoid y tanh unidades, y añadiendo un plazo de regularización a mi costo). El next_batch crea un lote al elegir aleatoriamente un conjunto de pares de entrada/salida de un conjunto de cerca de un millón de ejemplos con etiqueta. Si corto la capa oculta por completo, aprende muy bien.

HIDDEN_COUNT = 50

x = tf.placeholder("float", [None, FEATURE_COUNT])

Wh = init_weights((FEATURE_COUNT, HIDDEN_COUNT))
bh = tf.Variable(tf.zeros([HIDDEN_COUNT]))
h = tf.nn.relu(tf.matmul(x, Wh) + bh)

b = tf.Variable(tf.zeros([CATEGORY_COUNT]))
W = init_weights((HIDDEN_COUNT, CATEGORY_COUNT))
y = tf.nn.softmax(tf.matmul(h,W) + b)

y_ = tf.placeholder("float", [None,CATEGORY_COUNT])

cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(.0001).minimize( cross_entropy )

# Test trained model
correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_sum(tf.cast(correct_prediction, "float"))

Y luego, dentro de un bucle...

batch_xs, batch_ys = next_batch('train', batch_size)
train_step.run({x: batch_xs, y_: batch_ys})

Ejemplo de salida

Entrenamiento en 500k ejemplos, agrupados en lotes de 50 muestras, con una evaluación de prueba cada 200 lotes:

accuracy: 0.031     cost: 71674 after 0 examples
accuracy: 0.187     cost: 70403 after 10000 examples
accuracy: 0.186     cost: 69147 after 20000 examples
accuracy: 0.187     cost: 68044 after 30000 examples
accuracy: 0.189     cost: 66978 after 40000 examples
accuracy: 0.192     cost: 65939 after 50000 examples
accuracy: 0.185     cost: 65112 after 60000 examples
accuracy: 0.187     cost: 64278 after 70000 examples
accuracy: 0.182     cost: 63690 after 80000 examples
accuracy: 0.185     cost: 62865 after 90000 examples
accuracy: 0.191     cost: 62023 after 100000 examples
accuracy: 0.186     cost: 61644 after 110000 examples
accuracy: 0.187     cost: 61155 after 120000 examples
accuracy: 0.189     cost: 60647 after 130000 examples
accuracy: 0.188     cost: 60209 after 140000 examples
accuracy: 0.187     cost: 59964 after 150000 examples
accuracy: 0.184     cost: 59496 after 160000 examples
accuracy: 0.186     cost: 59261 after 170000 examples
accuracy: 0.185     cost: 59127 after 180000 examples
accuracy: 0.186     cost: 58839 after 190000 examples
accuracy: 0.187     cost: 58884 after 200000 examples
accuracy: 0.184     cost: 58723 after 210000 examples
accuracy: 0.184     cost: 58493 after 220000 examples
accuracy: 0.189     cost: 58221 after 230000 examples
accuracy: 0.187     cost: 58176 after 240000 examples
accuracy: 0.189     cost: 58092 after 250000 examples
accuracy: 0.183     cost: 58057 after 260000 examples
accuracy: 0.184     cost: 58040 after 270000 examples
accuracy: 0.181     cost: 58369 after 280000 examples
accuracy: 0.189     cost: 57762 after 290000 examples
accuracy: 0.182     cost: 58186 after 300000 examples
accuracy: 0.189     cost: 57703 after 310000 examples
accuracy: 0.188     cost: 57521 after 320000 examples
accuracy: 0.185     cost: 57804 after 330000 examples
accuracy: 0.184     cost: 57883 after 340000 examples
accuracy: 0.184     cost: 57756 after 350000 examples
accuracy: 0.186     cost: 57505 after 360000 examples
accuracy: 0.185     cost: 57569 after 370000 examples
accuracy: 0.186     cost: 57562 after 380000 examples
accuracy: 0.204     cost: 57406 after 390000 examples
accuracy: 0.211     cost: 57432 after 400000 examples
accuracy: 0.185     cost: 57576 after 410000 examples
accuracy: 0.182     cost: 57774 after 420000 examples
accuracy: 0.183     cost: 57520 after 430000 examples
accuracy: 0.184     cost: 57421 after 440000 examples
accuracy: 0.186     cost: 57374 after 450000 examples
accuracy: 0.183     cost: 57552 after 460000 examples
accuracy: 0.186     cost: 57435 after 470000 examples
accuracy: 0.181     cost: 57210 after 480000 examples
accuracy: 0.182     cost: 57493 after 490000 examples

Obsérvese que el intento de reducir la tasa de aprendizaje y reanudar después de estas muestras de entrenamiento de 500k no produjo ninguna mejora en la precisión ni en el costo.

5voto

dotancohen Puntos 595

Aquí están mis pensamientos sobre lo que podría ir mal:

Precisión (lo que se está midiendo)

Tal vez su red esté funcionando bien.

Consideremos la clasificación binomial. Si tenemos una distribución 50-50 de etiquetas, entonces el 50% de precisión significa que el modelo no es mejor que la casualidad (lanzando una moneda). Si la distribución de Bernoulli es de 80%-20% y la precisión es del 50%, entonces el modelo es peor que el azar.

No importa lo que intente, no veo más de un 20% de precisión cuando añado una capa oculta.

Si la precisión es del 20%, sólo anula la salida y tienes el 80% de precisión, ¡bien hecho! (bueno al menos para el caso del binomio).

¡No tan rápido!

Creo que en su caso la exactitud es engañosa. Este es una buena lectura sobre el asunto. Para la clasificación, el AUC (área bajo la curva) se utiliza a menudo. Es común también examinar la característica operativa del receptor (ROC) y la matriz de confusión.

Para el caso de las clases múltiples esto se vuelve más difícil. Aquí hay un responder a que encontré. En última instancia, esto implica una estrategia de 1-vs-descanso o pares 1-vs-1, más sobre eso aquí .

Preprocesamiento

  • ¿Están los rasgos a escala? ¿Tienen los mismos límites? Por ejemplo [0,1]

  • ¿Ha intentado estandarizar las características? Esto hace que cada característica se distribuya normalmente con una media cero y una variación unitaria.

  • ¿Quizás la normalización podría ayudar? Dividiendo cada vector de entrada por su norma lo coloca en el círculo de la unidad (para la norma L2) y también limita las características (pero la escala debe realizarse primero, de lo contrario los números más grandes se dispararán).

Entrenamiento

En cuanto a la velocidad y el impulso de aprendizaje, si no tienes mucha prisa, sólo establecería una velocidad de aprendizaje baja y el algoritmo convergería mejor (aunque más lentamente). Esto es válido para el descenso de gradiente estocástico donde los ejemplos se muestran al azar (¿estás barajando los datos?). A partir de tu código no puedo entender cómo sucede esto. ¿Vas a hacer una sola pasada por los datos de entrenamiento? Para el SGD, se hacen múltiples iteraciones. ¿Quizás probar con lotes más pequeños? ¿Has probado el decaimiento de peso como método de regularización?

Arquitectura

Cross-entropía como función de pérdida: comprobado. Softmax en las salidas: comprobado.

Puede que sea un tiro largo en este punto, pero ¿has intentado proyectarte a una dimensión más alta en la primera capa oculta y luego colapsar a un espacio más bajo en las siguientes dos capas ocultas?

También está el costo en su producción, me pregunto si podría ser escalado para tener más sentido. Yo trataría de trazar la evolución del costo (logaritmo de pérdida aquí) y ver si fluctúa o qué tan pronunciado es. Su red podría estar atascada en una meseta mínima local. O podría estar funcionando muy bien, en cuyo caso, ¿revisaría la métrica?

Espero que esto haya ayudado o haya generado algunas ideas nuevas.

EDITAR:

Ejemplo de cómo la normalización (L2) puede empeorar las cosas cuando las características no están escaladas en relación con las otras características. Gráficas para una muestra:

norming a vector before scaling

En la imagen de la izquierda la línea azul es un vector de 10 valores generados aleatoriamente con un cero medio y std de 1. En la imagen de la derecha añadí una característica 'atípica' o fuera de escala no.6 donde fijé su valor en 10. Claramente fuera de escala. Cuando normalizamos el vector fuera de escala, todos los demás rasgos se acercan mucho a 0 como se puede ver en la línea naranja de la derecha.

La estandarización de los datos podría ser una buena cosa a hacer antes que nada en este caso. Intenta trazar algunos histogramas de los rasgos o gráficos de cajas.

Mencionaste que estás normalizando los vectores para sumar a 1 y ahora funciona mejor con 10. Eso significa que estás dividiendo por la 1-norma = suma(abs(X)) en lugar de la 2-norma (euclidiano) = suma(abs(X).^2)^(1/2). La normalización L1 genera vectores más escasos, mira la figura de abajo, donde cada eje es una característica, por lo que este es un espacio bidimensional, sin embargo puede ser generalizado a un número arbitrario de dimensiones.

vector norms

La normalización coloca efectivamente cada vector en el borde de cualquiera de las formas. Para L1 se ubicará en el diamante en algún lugar. Para L2 en el círculo. Cuando golpea el eje es cero.

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