CIFAR-10 no puede superar el 60% de precisión, Keras con Tensorflow backend [cerrado]

11

El entrenamiento después de 15 épocas en el conjunto de datos CIFAR-10 parece hacer que la pérdida de validación ya no disminuya, permaneciendo alrededor de 1.4 (con una precisión de validación del 60%). He barajado el conjunto de entrenamiento, dividido entre 255 e importado como float32. He probado numerosas arquitecturas, con y sin abandono en las capas Conv2D y nada parece funcionar. La misma arquitectura logra una precisión del 99.7% en los conjuntos de prueba para MNIST. Por favor vea la arquitectura a continuación:

(Nota: he intentado aumentar el abandono y aumentar / disminuir la tasa de aprendizaje del optimizador Adam para evitar el sobreajuste, todo esto es evitar el sobreajuste, pero ahora tanto el entrenamiento como el conjunto de pruebas tienen una precisión baja similar alrededor del 60%).

with tf.device('/gpu:0'):
    tf.placeholder(tf.float32, shape=(None, 20, 64))
    #placeholder initialized (pick /cpu:0 or /gpu:0)
    seed = 6
    np.random.seed(seed)
    modelnn = Sequential()
    neurons = x_train_reduced.shape[1:]

    modelnn.add(Convolution2D(32, 3, 3, input_shape=neurons, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(32, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    #modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    #modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    #modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Flatten())
    #modelnn.add(Dropout(0.5))
    modelnn.add(Dense(1024, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(512, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(10, activation='softmax'))
    modelnn.compile(loss='categorical_crossentropy', optimizer=optimizer_input, metrics=['accuracy'])
    y_train = to_categorical(y_train)
    modelnn.fit(x_train_reduced, y_train, nb_epoch=nb_epoch_count, shuffle=True, batch_size=bsize,
                           validation_split=0.1)

Resultados:

    44100/44100 [==============================] - 22s - loss: 2.1453 - acc: 0.2010 - val_loss: 1.9812 - val_acc: 0.2959
    Epoch 2/50
    44100/44100 [==============================] - 24s - loss: 1.9486 - acc: 0.3089 - val_loss: 1.8685 - val_acc: 0.3567
    Epoch 3/50
    44100/44100 [==============================] - 18s - loss: 1.8599 - acc: 0.3575 - val_loss: 1.7822 - val_acc: 0.3982
    Epoch 4/50
    44100/44100 [==============================] - 18s - loss: 1.7925 - acc: 0.3933 - val_loss: 1.7272 - val_acc: 0.4229
    Epoch 5/50
    44100/44100 [==============================] - 18s - loss: 1.7425 - acc: 0.4195 - val_loss: 1.6806 - val_acc: 0.4459
    Epoch 6/50
    44100/44100 [==============================] - 18s - loss: 1.6998 - acc: 0.4440 - val_loss: 1.6436 - val_acc: 0.4682
    Epoch 7/50
    44100/44100 [==============================] - 18s - loss: 1.6636 - acc: 0.4603 - val_loss: 1.6156 - val_acc: 0.4837
    Epoch 8/50
    44100/44100 [==============================] - 18s - loss: 1.6333 - acc: 0.4781 - val_loss: 1.6351 - val_acc: 0.4776
    Epoch 9/50
    44100/44100 [==============================] - 18s - loss: 1.6086 - acc: 0.4898 - val_loss: 1.5732 - val_acc: 0.5063
    Epoch 10/50
    44100/44100 [==============================] - 18s - loss: 1.5776 - acc: 0.5065 - val_loss: 1.5411 - val_acc: 0.5227
    Epoch 11/50
    44100/44100 [==============================] - 18s - loss: 1.5585 - acc: 0.5145 - val_loss: 1.5485 - val_acc: 0.5212
    Epoch 12/50
    44100/44100 [==============================] - 18s - loss: 1.5321 - acc: 0.5288 - val_loss: 1.5354 - val_acc: 0.5316
    Epoch 13/50
    44100/44100 [==============================] - 18s - loss: 1.5082 - acc: 0.5402 - val_loss: 1.5022 - val_acc: 0.5427
    Epoch 14/50
    44100/44100 [==============================] - 18s - loss: 1.4945 - acc: 0.5438 - val_loss: 1.4916 - val_acc: 0.5490
    Epoch 15/50
    44100/44100 [==============================] - 192s - loss: 1.4762 - acc: 0.5535 - val_loss: 1.5159 - val_acc: 0.5394
    Epoch 16/50
    44100/44100 [==============================] - 18s - loss: 1.4577 - acc: 0.5620 - val_loss: 1.5389 - val_acc: 0.5257
    Epoch 17/50
    44100/44100 [==============================] - 18s - loss: 1.4425 - acc: 0.5671 - val_loss: 1.4590 - val_acc: 0.5667
    Epoch 18/50
    44100/44100 [==============================] - 18s - loss: 1.4258 - acc: 0.5766 - val_loss: 1.4552 - val_acc: 0.5763
    Epoch 19/50
    44100/44100 [==============================] - 18s - loss: 1.4113 - acc: 0.5805 - val_loss: 1.4439 - val_acc: 0.5767
    Epoch 20/50
    44100/44100 [==============================] - 18s - loss: 1.3971 - acc: 0.5879 - val_loss: 1.4473 - val_acc: 0.5769
    Epoch 21/50
    44100/44100 [==============================] - 18s - loss: 1.3850 - acc: 0.5919 - val_loss: 1.4251 - val_acc: 0.5871
    Epoch 22/50
    44100/44100 [==============================] - 18s - loss: 1.3668 - acc: 0.6006 - val_loss: 1.4203 - val_acc: 0.5910
    Epoch 23/50
    44100/44100 [==============================] - 18s - loss: 1.3549 - acc: 0.6051 - val_loss: 1.4207 - val_acc: 0.5939
    Epoch 24/50
    44100/44100 [==============================] - 18s - loss: 1.3373 - acc: 0.6111 - val_loss: 1.4516 - val_acc: 0.5784
    Epoch 25/50
    44100/44100 [==============================] - 18s - loss: 1.3285 - acc: 0.6149 - val_loss: 1.4146 - val_acc: 0.5922
    Epoch 26/50
    44100/44100 [==============================] - 18s - loss: 1.3134 - acc: 0.6205 - val_loss: 1.4090 - val_acc: 0.6024
    Epoch 27/50
    44100/44100 [==============================] - 18s - loss: 1.3043 - acc: 0.6239 - val_loss: 1.4307 - val_acc: 0.5959
    Epoch 28/50
    44100/44100 [==============================] - 18s - loss: 1.2862 - acc: 0.6297 - val_loss: 1.4241 - val_acc: 0.5978
    Epoch 29/50
    44100/44100 [==============================] - 18s - loss: 1.2706 - acc: 0.6340 - val_loss: 1.4046 - val_acc: 0.6067
    Epoch 30/50
    44100/44100 [==============================] - 18s - loss: 1.2634 - acc: 0.6405 - val_loss: 1.4120 - val_acc: 0.6037
    Epoch 31/50
    44100/44100 [==============================] - 18s - loss: 1.2473 - acc: 0.6446 - val_loss: 1.4067 - val_acc: 0.6045
    Epoch 32/50
    44100/44100 [==============================] - 18s - loss: 1.2411 - acc: 0.6471 - val_loss: 1.4083 - val_acc: 0.6098
    Epoch 33/50
    44100/44100 [==============================] - 18s - loss: 1.2241 - acc: 0.6498 - val_loss: 1.4091 - val_acc: 0.6076
    Epoch 34/50
    44100/44100 [==============================] - 18s - loss: 1.2121 - acc: 0.6541 - val_loss: 1.4209 - val_acc: 0.6127
    Epoch 35/50
    44100/44100 [==============================] - 18s - loss: 1.1995 - acc: 0.6582 - val_loss: 1.4230 - val_acc: 0.6131
    Epoch 36/50
    44100/44100 [==============================] - 18s - loss: 1.1884 - acc: 0.6622 - val_loss: 1.4024 - val_acc: 0.6124
    Epoch 37/50
    44100/44100 [==============================] - 18s - loss: 1.1778 - acc: 0.6657 - val_loss: 1.4328 - val_acc: 0.6080
    Epoch 38/50
    44100/44100 [==============================] - 18s - loss: 1.1612 - acc: 0.6683 - val_loss: 1.4246 - val_acc: 0.6159
    Epoch 39/50
    44100/44100 [==============================] - 18s - loss: 1.1466 - acc: 0.6735 - val_loss: 1.4282 - val_acc: 0.6122
    Epoch 40/50
    44100/44100 [==============================] - 18s - loss: 1.1325 - acc: 0.6783 - val_loss: 1.4311 - val_acc: 0.6157
    Epoch 41/50
    44100/44100 [==============================] - 18s - loss: 1.1213 - acc: 0.6806 - val_loss: 1.4647 - val_acc: 0.6047
    Epoch 42/50
    44100/44100 [==============================] - 18s - loss: 1.1064 - acc: 0.6842 - val_loss: 1.4631 - val_acc: 0.6047
    Epoch 43/50
    44100/44100 [==============================] - 18s - loss: 1.0967 - acc: 0.6870 - val_loss: 1.4535 - val_acc: 0.6106
    Epoch 44/50
    44100/44100 [==============================] - 18s - loss: 1.0822 - acc: 0.6893 - val_loss: 1.4532 - val_acc: 0.6149
    Epoch 45/50
    44100/44100 [==============================] - 18s - loss: 1.0659 - acc: 0.6941 - val_loss: 1.4691 - val_acc: 0.6108
    Epoch 46/50
    44100/44100 [==============================] - 18s - loss: 1.0610 - acc: 0.6956 - val_loss: 1.4751 - val_acc: 0.6106
    Epoch 47/50
    44100/44100 [==============================] - 18s - loss: 1.0397 - acc: 0.6981 - val_loss: 1.4857 - val_acc: 0.6041
    Epoch 48/50
    44100/44100 [==============================] - 18s - loss: 1.0208 - acc: 0.7039 - val_loss: 1.4901 - val_acc: 0.6106
    Epoch 49/50
    44100/44100 [==============================] - 18s - loss: 1.0187 - acc: 0.7036 - val_loss: 1.4994 - val_acc: 0.6106
    Epoch 50/50
    44100/44100 [==============================] - 18s - loss: 1.0024 - acc: 0.7070 - val_loss: 1.5078 - val_acc: 0.6039
    Time: 1109.7512991428375
    Neural Network now trained from dimensions (49000, 3, 32, 32)

Actualización: Pruebas adicionales que incluyen BatchNormalization con y sin MaxNorm -

img

Nueva arquitectura:

    modelnn.add(Convolution2D(32, 3, 3, input_shape=neurons, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(32, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(64, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.2))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
    modelnn.add(BatchNormalization())
    modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Dropout(0.2))
    # modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    # modelnn.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
    # modelnn.add(MaxPooling2D(pool_size=(2, 2)))
    modelnn.add(Flatten())
    modelnn.add(Dense(1024, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(512, activation='relu', W_constraint=maxnorm(3)))
    modelnn.add(BatchNormalization())
    modelnn.add(Dropout(0.5))
    modelnn.add(Dense(10, activation='softmax'))
usuario4779
fuente

Respuestas:

8

Tenga en cuenta que MNIST es un conjunto de problemas mucho más simple que CIFAR-10, y puede obtener el 98% de una NNet completamente conectada (no convolucional) con muy poca dificultad. Una CNN muy simple con solo una o dos capas convolucionales también puede alcanzar el mismo nivel de precisión.

No estoy seguro acerca de su arquitectura NNet, pero puedo obtener una precisión de prueba del 78% en CIFAR-10 con la siguiente arquitectura (que es comparativamente más simple y tiene menos pesos). No se requirió una inicialización o retención especial, utilizando los valores predeterminados de vainilla y el optimizador Adam:

model = Sequential()
model.add(Conv2D(input_shape=trainX[0,:,:,:].shape, filters=96, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=96, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Conv2D(filters=192, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Conv2D(filters=192, kernel_size=(3,3), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(BatchNormalization())
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dense(n_classes, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])

Esta arquitectura es bastante simple y se basa libremente en https://arxiv.org/pdf/1412.6806.pdf .

Entrenando este modelo de esta manera:

n_epochs = 25
batch_size = 256
callbacks_list = None
H = model.fit(trainX, trainY, validation_data=(testX, testY), 
              epochs=n_epochs, batch_size=batch_size, callbacks=callbacks_list)
print('Done!!!')

Da lo siguiente, que puede ver que llega a casi el 77% en la 25a época y se aplana más o menos desde allí (pero tiene suficiente regularización desde la deserción para evitar que se degrade debido al sobreajuste, al menos durante el número de iteraciones probado) .

Entrene en 50000 muestras, valide en 10000 muestras
Época 1/50
50000/50000 [==============================] - 19s 390us / paso - pérdida: 1.6058 - acc: 0.4150 - val_loss: 1.5285 - val_acc: 0.4669
Epoch 2/50
50000/50000 [======================= =======] - 19s 371us / paso - pérdida: 1.2563 - acc: 0.5477 - val_loss: 1.1447 - val_acc: 0.5901
Epoch 3/50
50000/50000 [============= =================] - 19s 373us / paso - pérdida: 1.0784 - acc: 0.6163 - val_loss: 1.1577 - val_acc: 0.6002
...
Epoch 25/50
50000/50000 [ ==============================] - 19s 374us / paso - pérdida: 0.3188 - acc: 0.8857 - val_loss: 0.7493 - val_acc : 0.7680
...
Época 50/50
50000/50000 [==============================] - 19s 373us / step - pérdida: 0.1928 - acc: 0.9329 - val_loss : 0.8718 - val_acc: 0.7751
¡Listo!

Aquí hay una arquitectura aún más simple y mucho más pequeña que puede llegar al 70% bastante rápido con el mismo régimen de entrenamiento (sin BatchNormalization o agrupación de capas):

# CNN architecture with Keras
model = Sequential()
model.add(Conv2D(input_shape=trainX[0,:,:,:].shape, filters=32, 
                 use_bias=True, kernel_size=(3,3)))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Conv2D(filters=64, use_bias=False, kernel_size=(5,5), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Flatten())
model.add(Dense(128))
model.add(Activation('relu'))
model.add(Dropout(0.3))
model.add(Dense(n_classes, activation="softmax"))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=    ['accuracy'])

Vale la pena señalar que las arquitecturas que obtienen la precisión mejor publicada en CIFAR-10 (actualmente en el rango de 90-96%) son generalmente más complicadas y tardan muchas horas en entrenarse en hardware de GPU. Pero he podido llegar al rango del 70-80% con arquitecturas bastante simples que entrenan en minutos, que es lo que recomendaría antes de obtener los mejores resultados publicados, que generalmente requieren arquitecturas más complicadas, períodos de entrenamiento más largos, a veces regímenes especiales de sujeción / entrenamiento o aumento de datos, y horas de tiempo de entrenamiento.

ACTUALIZAR:

Según los gráficos actualizados en la pregunta, el problema más obvio que se demuestra es el sobreajuste. Esto se evidencia por la divergencia de los datos de la prueba del tren después de aproximadamente la 15ª época, lo que demuestra una regularización insuficiente para esta arquitectura, para este conjunto de datos. Es poco probable que obtenga mejoras al ajustar otros hiperparámetros (estrategias de normalización, tasas de aprendizaje, etc.) a menos que se aborde el sobreajuste.

Al usar NNets, recomiendo lo siguiente:

  1. Comience desde arquitecturas que imitan o replican las que se sabe que producen buenos resultados
  2. Verifique el rendimiento en su conjunto de datos, con especial atención al sobreajuste en la red (evidenciado por una divergencia significativa de errores de prueba de tren)
  3. Agregue regularización adicional (aumente las tasas de deserción) cuando se observe un sobreajuste (está buscando "lo suficiente" para evitar el sobreajuste; demasiado resultará en un ajuste insuficiente)
  4. Experimente con la estructura, los enfoques de capacitación y los hiperparámetros para encontrar vías de mejora.

Las recetas con respecto a este último en realidad son bastante difíciles de conseguir, porque hay pocos fundamentos teóricos sobre cómo la estructura, el entrenamiento o los hiperparámetros interactúan para producir rendimiento en cualquier conjunto de datos dado. Es evidente que los enfoques empleados por las arquitecturas publicadas que alcanzan niveles de rendimiento similares en los conjuntos de datos de referencia varían mucho.

Se ha descubierto que la baticormalización mejora significativamente algunas arquitecturas, pero otras pueden funcionar bastante bien sin ellas (o son indiferentes a su presencia). La única guía real para proporcionar aquí es probarlo y ver si ayuda.

Por lo general, debe evitarse el ajuste de las tasas de aprendizaje a menos que sea un profesional avanzado con un profundo conocimiento de ConvNets y la capacidad correspondiente para leer las hojas de té con respecto al rendimiento incremental entre épocas durante el entrenamiento. Las tasas de aprendizaje personalizadas y otros regímenes de capacitación especializados pueden, en algunos casos, ayudar a las redes a navegar por los mínimos locales y encontrar mejores soluciones generales, pero a menos que tenga mucho tiempo y los conocimientos para diagnosticar el comportamiento de convergencia de la red, esto no es Un buen lugar para comenzar. La mayoría de nosotros debería usar un optimizador como Adam que superará los intentos de los novatos en las tasas de aprendizaje ajustadas a mano en la gran mayoría de los casos.

El aumento de datos a través del preprocesamiento de imágenes a veces puede producir mejoras significativas en el rendimiento (en general, cuanto más variados sean los datos de entrada, mejor generalizará el modelo; el preprocesamiento de datos agrega variación al espacio de entrada que puede mejorar la precisión fuera de la muestra y puedepermitir una reducción en los requisitos de regularización: hipotéticamente, con datos de entrenamiento infinitos no necesitaríamos ninguna regularización en absoluto, pero en el espacio de procesamiento de imágenes es poco probable que abordemos esa asíntota). Sin embargo, esto puede aumentar significativamente el tiempo de entrenamiento y disminuir las tasas de convergencia, e introduce un conjunto completamente diferente de hiperparámetros relacionados con las técnicas de permutación de imágenes de entrada (rotación, recorte, escala, ruido, etc., etc.). Debido a que esta ruta puede aumentar los tiempos de entrenamiento y requerir experimentos adicionales para ajustar los resultados, algunos consejos generales serían conducir para obtener la mejor precisión en su red sin aumento primero, luego ver si algún aumento modesto produce una mejora. Si lo hace, puede justificar una mayor experimentación.

Para todos y cada uno de los experimentos de ajuste, deberá estar atento a los cambios en el comportamiento de ajuste excesivo o insuficiente. Cambiar la arquitectura de la red, los regímenes de entrenamiento o los hiperparámetros puede requerir un ajuste adicional de la regularización de abandono. La capacidad de determinar fácilmente el comportamiento de ajuste excesivo o insuficiente del rendimiento del tren / prueba es posiblemente la habilidad de referencia más importante para trabajar con NNets, y esto se vuelve más intuitivo con la experiencia.

Esta es la vela por la cual todos sus esfuerzos serán guiados. La vela solo puede iluminar tenuemente el camino, pero sin ella tropezarás en la oscuridad. Si su red tiene un ajuste excesivo o insuficiente, esto debe abordarse antes de intentar permutaciones aleatorias de la estructura de la red o hiperparámetros.

Las arquitecturas comparativamente simples con los regímenes de entrenamiento de vainilla incluidos en esta respuesta demuestran la realidad de trabajar con arquitecturas NNET en problemas difíciles como la clasificación de imágenes: lograr un resultado "bastante bueno" basado en enfoques que se sabe que funcionan bien no es difícil, pero la mejora incremental Es cada vez más costoso. Lograr los mejores resultados publicados a través de la experimentación va a estar más allá de las capacidades o la disponibilidad de tiempo de muchos (aunque es posible, con suficiente tiempo y esfuerzo, seguir las recetas del libro de cocina de los enfoques publicados para replicar sus resultados, pero incluso esto no es posible significa trivial). Lograr una mejora incremental desde un punto de partida "bastante bueno" puede ser un proceso de prueba y error que lleva mucho tiempo, y muchos experimentos no producirán ninguna mejora significativa.

Esto no pretende disuadir a nadie de intentar aprender, sino solo para dejar en claro que se requiere una inversión significativa para dominar el conjunto de herramientas (siempre en expansión) en la bolsa de trucos de NNet, e impulsar mejoras a través de prueba y error puede requerir docenas (o cientos) de experimentos durante días o semanas de entrenamiento dedicado en GPU.

El tiempo, la habilidad y los recursos (GPU dedicada) requeridos para entrenar redes a niveles muy altos de rendimiento explican en parte la popularidad de las redes pre-entrenadas.

T3am5hark
fuente
1
¿Las arquitecturas de red neuronal no tienen capas de agrupación? ¿no crea eso un número inmanejable de parámetros?
Spandyie
2
Pooling - pfft! Sobrevalorado Esto utiliza un enfoque totalmente convolucional que utiliza el paso a paso para la aniquilación en lugar de la agrupación; consulte el documento vinculado para obtener una descripción. La zancada convolucional puede obtener el mismo efecto de "canalización" que la agrupación por medios ligeramente diferentes. El hecho de que ambos funcionen simplemente ilustra que no hay mucho fundamento teórico firme sobre el que pensar por qué funciona todo esto.
T3am5hark
6

Al observar sus valores de pérdida y precisión dentro y fuera de la muestra, su modelo actualmente no está equipado, pero está mejorando de forma monótona. En otras palabras, parece que ejecutar esto durante más épocas daría como resultado un mayor rendimiento predictivo / menos pérdida de entropía.

Está utilizando una arquitectura altamente regularizada (capas de abandono), que no está mal. Sin embargo, tampoco es sorprendente que el entrenamiento tome mucho más tiempo que sin ninguna regularización. Debido a las capas de abandono, es poco probable que se sobreajuste (sustancialmente).

Cosas que puedes intentar para acelerar el aprendizaje:

yo. ajustar la tasa de aprendizaje: por ejemplo, comenzar con una pequeña, subirla por la mitad y hacia el final bajarla nuevamente.

ii. agregue batchnormalisation : en la arquitectura anterior, puede incluir la norma de lote tanto en sus bloques convolucionales como en capas densas. Por lo general, la capa de la norma de lote se agrega después de la activación no lineal pero antes del abandono. No estoy seguro de qué tan bien juega la norma de lotes con maxnorm. Para sus capas densas, probaría lote-norma + dropuout con / sin maxnorm. Tengo la sensación de que no necesita maxnorm si aplica la normalización por lotes.

iii) aumentar el tamaño del lote: no estoy seguro de cuál es su tamaño de lote y si posee una GPU. Si tiene una GPU, probablemente debería intentar maximizar el tamaño de su lote en multiplicativos de 32.

Finalmente, para garantizar que sus datos sean 'aprendebles' / no estén corruptos (por ejemplo, no ha aplicado involuntariamente una transformación para deformarlos), descartaría toda la regularización de su arquitectura, ejecutaría el entrenamiento y vería que puede adaptarse al conjunto de entrenamiento . Si puede aprender datos de entrenamiento con éxito, el resto es un ejercicio de generalización. Si no puede adaptarse demasiado a los datos de entrenamiento incluso sin regularización, lo más probable es que su modelo necesite más capacidad (arquitectura más profunda y más amplia).

Zhubarb
fuente
Gracias amablemente por el consejo! Tenías razón sobre MaxNorm interfiriendo ligeramente. Sin embargo, incluso después de agregar las capas de BatchNormalization (ver actualización) y eliminar / incluir MaxNorm, la precisión sigue siendo baja. Tampoco se lleva a cabo el aumento. Tengo una GPU y he intentado entrenar a 64,128,256 y 512 lotes, pero se nota poca diferencia. En cuanto a la tasa de aprendizaje, estoy usando el optimizador Adam y pensé que esto debería dejarse más o menos solo. Sin embargo, probé LR a 0.05, 0.001, 0.0005 y noté que el valor predeterminado de 0.001 parece mejor aún. ¿Algunas ideas?
user4779
También soy capaz de sobreajustar bien. Hice mi mejor esfuerzo para copiar la arquitectura en los documentos que parecen ser capaces de lograr una precisión del 80% ++ con MNIST10. Cuando dejo el modelo de entrenamiento para épocas más largas, parece que la pérdida ahora aumenta (más de 20 épocas más o menos).
user4779
Comentario de modificación: después de los cambios en el modelo, los gráficos ahora indican que está sobreajustando significativamente los datos (en base a la divergencia del error de validación después de ~ 15 épocas)
T3am5hark
De hecho, disputo la utilidad de los consejos que se ofrecen aquí, especialmente para los nuevos profesionales. Estas son todas las cosas que puede hacer, seguro, pero para las personas que son nuevas en CNN y no tienen la intuición o la comprensión de cómo funcionan estas cosas, son demasiados mandos y palancas para ajustar sin ninguna guía prescriptiva que no sea un ensayo ciego y error, poco probable que produzca resultados positivos. Mejor sería comenzar primero con arquitecturas más simples que sean capaces de obtener un buen rendimiento (no mejor publicado) con un mínimo giro, y luego explorar vías de mejora desde allí. Mis dos centavos.
T3am5hark
Para más detalles: no juegues con las tasas de aprendizaje, usa Adam. Va a superar el ajuste manual de las tasas de aprendizaje el 99,99% del tiempo. Además, la afirmación de que es "poco probable que alguna vez se sobreajuste" es simplemente errónea (como lo indican los gráficos de seguimiento que ahora demuestran un sobreajuste significativo), y no hay una buena razón para que el póster asuma que ... no hay nada que le diga a priori para una arquitectura dada si una tasa de deserción determinada se regularizará lo suficiente como para evitar un ajuste excesivo.
T3am5hark
1

Intenté esto hoy y pude alcanzar casi el 75-80% en precisión de prueba.

Historia de entrenamiento

  • El número total de parámetros utilizados fue: 183,242

  • Puede hacerlo mejor agregando quizás unas pocas capas más, pero no necesita ser excesivo. Las redes más complejas no siempre resultan en mejores resultados.

Sugerencias

Mi sugerencia para usted es que mantenga su arquitectura simple. Sigue la navaja de Occam , simple es mejor.

  • Escala tus datos

  • No uses una semilla aleatoria

  • Use un optimizador apropiado; Usé Adadelta como es de Keras.

  • Las CNN no necesitan ser enrevesadas; mantenlo simple

  • Las redes más delgadas y profundas a veces funcionan mejor que las más anchas

  • Usar regularización (por ejemplo, abandono)

A continuación se muestra mi código (usando Keras)

# Define the model
model = Sequential()
model.add(Convolution2D(64, (4, 4), padding='same', input_shape=(3, 32, 32)))
model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(64, (2, 2), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Convolution2D(32, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), strides=2))
model.add(Dropout(0.15))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.25))
model.add(Dense(64))
model.add(Activation('tanh'))
model.add(Dropout(0.25))
model.add(Dense(num_classes, activation='softmax'))
# Compile the model
Jon
fuente