Estoy entrenando una red neuronal convolucional simple para la regresión, donde la tarea es predecir la ubicación (x, y) de un cuadro en una imagen, por ejemplo:
La salida de la red tiene dos nodos, uno para xy otro para y. El resto de la red es una red neuronal convolucional estándar. La pérdida es un error cuadrático medio estándar entre la posición predicha de la caja y la posición de verdad del suelo. Estoy entrenando en 10000 de estas imágenes y validando en 2000.
El problema que tengo es que, incluso después de un entrenamiento significativo, la pérdida realmente no disminuye. Después de observar la salida de la red, noto que la red tiende a generar valores cercanos a cero, para ambos nodos de salida. Como tal, la predicción de la ubicación del cuadro siempre es el centro de la imagen. Hay alguna desviación en las predicciones, pero siempre alrededor de cero. A continuación se muestra la pérdida:
He ejecutado esto durante muchas más épocas de las que se muestran en este gráfico, y la pérdida aún nunca disminuye. Curiosamente aquí, la pérdida en realidad aumenta en un punto.
Entonces, parece que la red solo está prediciendo el promedio de los datos de entrenamiento, en lugar de aprender un buen ajuste. ¿Alguna idea de por qué esto puede ser? Estoy usando a Adam como optimizador, con una tasa de aprendizaje inicial de 0.01, y relus como activaciones
Si está interesado en algo de mi código (Keras), está a continuación:
# Create the model
model = Sequential()
model.add(Convolution2D(32, 5, 5, border_mode='same', subsample=(2, 2), activation='relu', input_shape=(3, image_width, image_height)))
model.add(Convolution2D(64, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Convolution2D(128, 5, 5, border_mode='same', subsample=(2, 2), activation='relu'))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dense(2, activation='linear'))
# Compile the model
adam = Adam(lr=0.01, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0)
model.compile(loss='mean_squared_error', optimizer=adam)
# Fit the model
model.fit(images, targets, batch_size=128, nb_epoch=1000, verbose=1, callbacks=[plot_callback], validation_split=0.2, shuffle=True)
Respuestas:
El optimizador no puede converger a una solución (sub) óptima. ¿Por qué? Su problema es demasiado fácil y / o su modelo es demasiado complejo.
Problema demasiado fácil
Como @photox ya dijo, este problema se puede resolver con una sola capa oculta. Incluso sospecho que se puede hacer sin una capa oculta. Esto se debe a que este problema es lineal separable .
Déjame ilustrar esto. Imagine una red neuronal sin capas ocultas y una función de activación lineal (también podría llamarse regresión lineal). Para calcular la ubicación x del cuadrado, cada píxel se conecta a la salida x. La primera columna de píxeles está conectada con el peso . La segunda columna está conectada con el peso . Esto continúa hasta la última columna (por ejemplo, la columna ) que está conectada con el peso . Desde2 / alto ancho n n / alto ancho alto ∗ ancho1 / altura / ancho 2 / ancho de altura norte n / altura ancho altura ∗ ancho los píxeles no son cero (por ejemplo, el sesgo es igual al valor del color gris), la activación de la salida x es igual al centro del cuadrado. Por lo tanto, una función lineal puede calcular la ubicación del cuadrado.
Hay varias soluciones:
Modelo demasiado complejo
Su modelo tiene algunas partes que agregan mucha complejidad sin ayudar al optimizador a encontrar un óptimo óptimo.
Por ejemplo, las capas convolucionales. La primera capa tiene 32 filtros convolucionales de tamaño . ¿Qué esperas que aprendan estos filtros? En la clasificación de imágenes, estos filtros aprenden a detectar bordes, esquinas, degradados y manchas. Pero en este caso solo hay unos pocos filtros que tienen sentido. Puedo pensar en el borde de izquierda a derecha y viceversa y de arriba a abajo y viceversa. En su caso, existen aproximadamente 28 filtros que solo agregan ruido aleatorio. Eliminarlos (o solo la capa completa) hace que sea mucho más fácil para el optimizador encontrar un óptimo que funcione.5 × 5
Otro ejemplo es el optimizador Adam con muchos parámetros adicionales. El optimizador Adam podría funcionar bien con estos parámetros, pero ¿por qué no comenzar con un simple
SGD
optimizador con valores predeterminados?Por lo tanto, puede hacer varias optimizaciones:
LinearRegression
de scikit-learn. OK, esto no es lo que quieres, pero solo quiero ilustrar cuán excesivamente complejo es este modelo.Dense
capas ocultas.SGD
optimizador predeterminadosigmoid
activación. Puede pensar que cada uno de los nodos de la capa oculta detecta si un cuadrado está en una ubicación determinada.PD
Creo que te gustará esta publicación de blog de Adit Deshpande.
fuente
Parece un problema típico de sobreajuste. Sus datos no proporcionan suficiente información para obtener el mejor resultado. Eliges el NN complejo con tu tren para recordar todos los matices de los datos del tren . La pérdida nunca puede ser un cero, como está en su gráfico. Por cierto, parece que su validación tiene un error o el conjunto de validación no es bueno para la validación porque la pérdida de validación también se está volviendo cero.
fuente
Estoy enfrentando el mismo problema con mi conjunto de datos. Resulta que en mi caso los predictores están altamente concentrados con una variación muy pequeña. Debe verificar la varianza de sus variables de predicción y ver cómo se distribuye.
Sin embargo, algunas transformaciones en la variable de salida se pueden realizar para modificar o cambiar su escala. Esto podría resultar en una distribución de tipo más uniforme. Por ejemplo, en las tareas de reconocimiento de imágenes, la ecualización del histograma o la mejora del contraste a veces funcionan a favor de la toma de decisiones correcta.
fuente
En realidad estaba trabajando en un problema muy similar. Básicamente, tenía un montón de puntos sobre un fondo blanco y estaba entrenando a un NN para reconocer el punto que se colocó primero en el fondo. La forma en que encontré que funcionaba era usar una capa de neuronas completamente conectadas (es decir, una NN de 1 capa). Por ejemplo, para una imagen de 100x100, tendría 10.000 neuronas de entrada (los píxeles) conectadas directamente a 2 neuronas de salida (las coordenadas). En PyTorch, cuando convertí los valores de píxeles a un tensor, estaba normalizando mis datos automáticamente, restando la media y dividiendo por la desviación estándar. En problemas normales de aprendizaje automático, esto está bien, pero no para una imagen en la que puede haber una disparidad en la cantidad de píxeles coloreados en una imagen (es decir, la suya donde solo hay unos pocos píxeles blancos). Entonces, Normalicé manualmente dividiendo todos los valores de intensidad de píxeles por 255 (por lo que ahora están en el rango de 0-1 sin la técnica de normalización típica que intenta ajustar todos los valores de intensidad a una distribución normal). Entonces, todavía tenía problemas porque predecía la coordenada promedio de los píxeles en el conjunto de entrenamiento. Entonces, mi solución fue establecer una tasa de aprendizaje muy alta, que va en contra de casi todos los instructores y tutoriales de ML. En lugar de usar 1e-3, 1e-4, 1e-5, como dice la mayoría de la gente, estaba usando una tasa de aprendizaje de 1 o 0.1 con descenso de gradiente estocástico. Esto solucionó mis problemas y mi red finalmente aprendió a memorizar mi conjunto de entrenamiento. No se generaliza demasiado bien a un conjunto de pruebas, pero al menos funciona, lo cual es una mejor solución que la mayoría de los demás sugirió en su pregunta. ahora está en el rango de 0-1 sin la técnica de normalización típica que intenta ajustar todos los valores de intensidad a una distribución normal). Entonces, todavía tenía problemas porque predecía la coordenada promedio de los píxeles en el conjunto de entrenamiento. Entonces, mi solución fue establecer una tasa de aprendizaje muy alta, que va en contra de casi todos los instructores y tutoriales de ML. En lugar de usar 1e-3, 1e-4, 1e-5, como dice la mayoría de la gente, estaba usando una tasa de aprendizaje de 1 o 0.1 con descenso de gradiente estocástico. Esto solucionó mis problemas y mi red finalmente aprendió a memorizar mi conjunto de entrenamiento. No se generaliza demasiado bien a un conjunto de pruebas, pero al menos funciona, lo cual es una mejor solución que la mayoría de los demás sugirió en su pregunta. ahora está en el rango de 0-1 sin la técnica de normalización típica que intenta ajustar todos los valores de intensidad a una distribución normal). Entonces, todavía tenía problemas porque predecía la coordenada promedio de los píxeles en el conjunto de entrenamiento. Entonces, mi solución fue establecer una tasa de aprendizaje muy alta, que va en contra de casi todos los instructores y tutoriales de ML. En lugar de usar 1e-3, 1e-4, 1e-5, como dice la mayoría de la gente, estaba usando una tasa de aprendizaje de 1 o 0.1 con descenso de gradiente estocástico. Esto solucionó mis problemas y mi red finalmente aprendió a memorizar mi conjunto de entrenamiento. No se generaliza demasiado bien a un conjunto de pruebas, pero al menos funciona, lo cual es una mejor solución que la mayoría de los demás sugirió en su pregunta.
fuente