CIFAR-10 Não é possível obter precisão acima de 60%, Keras com back-end Tensorflow [fechado]

11

O treinamento após 15 épocas no conjunto de dados CIFAR-10 parece fazer com que a perda de validação não diminua mais, ficando em torno de 1,4 (com precisão de validação de 60%). Eu embaralhei o conjunto de treinamento, o dividi por 255 e importei como float32. Eu tentei várias arquiteturas, com e sem desistência nas camadas Conv2D e nada parece funcionar. A mesma arquitetura atinge 99,7% de precisão nos conjuntos de teste para MNIST. Por favor, veja a arquitetura abaixo:

(Observação: tentei aumentar a evasão e aumentar / diminuir a taxa de aprendizado do otimizador Adam para evitar o excesso de ajustes; tudo isso faz com que o excesso de ajustes seja necessário, mas com o treinamento e o conjunto de testes agora com baixa precisão semelhante em torno de 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)

Atualização: Novos testes, incluindo BatchNormalization, com e sem MaxNorm -

img

Nova arquitetura:

    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'))
user4779
fonte

Respostas:

8

Observe que o MNIST é um conjunto de problemas muito mais simples que o CIFAR-10 e você pode obter 98% de uma NNet totalmente conectada (não convolucional) com muito pouca dificuldade. Uma CNN muito simples, com apenas uma ou duas camadas convolucionais, também pode obter o mesmo nível de precisão.

Não tenho certeza sobre sua arquitetura NNet, mas posso obter 78% de precisão de teste no CIFAR-10 com a seguinte arquitetura (que é comparativamente mais simples e tem menos pesos). Nenhuma inicialização ou pega especial foi necessária, usando os padrões de baunilha e o otimizador 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'])

Essa arquitetura é bastante simples e é vagamente baseada em https://arxiv.org/pdf/1412.6806.pdf .

Treinando este modelo assim:

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!!!')

Fornece o seguinte, que você pode ver chega a quase 77% até a 25ª época e mais ou menos nivela a partir daí (mas tem regularização suficiente do abandono para impedir que ele se degrade devido ao super ajuste, pelo menos sobre o número testado de iterações) .

Treine em 50000 amostras, valide em 10000 amostras
Época 1/50
50000/50000 [=============================== - 19s 390us / step - perda: 1.6058 - acc: 0.4150 - val_loss: 1.5285 - val_acc: 0.4669
Época 2/50
50000/50000 [======================= =======] - 19s 371us / step - perda: 1.2563 - acc: 0.5477 - val_loss: 1.1447 - val_acc: 0.5901
Época 3/50
50000/50000 [============= =================] - 19s 373us / step - perda: 1.0784 - acc: 0.6163 - perda de val: 1.1577 - val_acc: 0.6002
...
Época 25/50
50000/50000 [ ==============================] - 19s 374us / step - perda: 0.3188 - acc: 0.8857 - val_loss: 0.7493 - val_acc : 0,7680
...
Época 50/50
50000/50000 [==============================] - 19s 373us / step - perda: 0.1928 - acc: 0.9329 - val_loss : 0,8718 - val_acc: 0,7751
Concluído !!!

Aqui está uma arquitetura ainda mais simples e muito menor que pode chegar a 70% rapidamente com o mesmo regime de treinamento (sem BatchNormalization ou pooling layers):

# 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 ressaltar que as arquiteturas que obtêm a melhor precisão publicada no CIFAR-10 (atualmente na faixa de 90 a 96%) são geralmente mais complicadas e levam muitas horas para serem treinadas no hardware da GPU. Mas consegui chegar ao intervalo de 70 a 80% com arquiteturas bastante simples que treinam em minutos, o que eu recomendaria antes de obter os melhores resultados publicados, que geralmente exigem arquiteturas mais complicadas, períodos de treinamento mais longos, Às vezes, regimes especiais de retenção / treinamento ou aumento de dados e horas de tempo de trem.

ATUALIZAR:

Com base nas plotagens atualizadas da pergunta, o problema mais óbvio demonstrado é o ajuste excessivo. Isso é evidenciado pela divergência dos dados do teste de trem após aproximadamente a época 15, que demonstra regularização insuficiente para essa arquitetura, para esse conjunto de dados. É improvável que você obtenha melhorias ao ajustar outros hiperparâmetros (estratégias de normalização, taxas de aprendizado etc.), a menos que o ajuste excessivo seja resolvido.

Ao usar NNets, recomendo o seguinte:

  1. Comece com arquiteturas que imitem ou repliquem aquelas conhecidas por produzir bons resultados
  2. Verifique o desempenho do seu conjunto de dados, com especial atenção ao excesso de ajustes na rede (evidenciado por divergência significativa de erros nos testes de trem)
  3. Adicione regularização adicional (aumente as taxas de desistência) quando for observado um ajuste excessivo (você está procurando "apenas o suficiente" para evitar o ajuste excessivo - muito resultará em ajuste insuficiente)
  4. Experimente a estrutura, as abordagens de treinamento e os hiper-parâmetros para encontrar avenidas de melhoria

As prescrições relativas a este último são realmente muito difíceis de encontrar, porque há pouco fundamento teórico sobre como a estrutura, o treinamento ou os hiperparâmetros interagem para obter desempenho em qualquer conjunto de dados. O fato de as abordagens empregadas pelas arquiteturas publicadas atingirem níveis de desempenho similarmente altos nos conjuntos de dados de referência varia muito é uma evidência disso.

Verificou-se que a normalização em lote melhora significativamente algumas arquiteturas, mas outras podem se sair muito bem sem ela (ou são indiferentes à sua presença). A única orientação real a ser fornecida aqui é experimentá-lo e ver se isso ajuda.

As taxas de aprendizado de ajuste fino geralmente devem ser evitadas, a menos que você seja um profissional avançado, com um profundo conhecimento das ConvNets e a capacidade correspondente de ler as folhas de chá em relação ao desempenho incremental entre as épocas durante o treinamento. Taxas de aprendizado personalizadas e outros esquemas de treinamento especializado podem, em alguns casos, ajudar as redes a navegar pelos mínimos locais e encontrar melhores soluções gerais, mas, a menos que você tenha muito tempo e o conhecimento necessário para diagnosticar o comportamento de convergência da rede, isso não é o caso. Um bom lugar para começar. A maioria de nós deve usar um otimizador como Adam, que superará as tentativas de iniciantes de taxas de aprendizado ajustadas à mão na grande maioria dos casos.

O aumento de dados via pré-processamento de imagem às vezes pode produzir melhorias significativas de desempenho (em geral, quanto mais variados forem os dados de entrada, melhor o modelo será generalizado - o pré-processamento de dados adiciona variação ao espaço de entrada, o que pode melhorar a precisão fora da amostra e podepermitir redução nos requisitos de regularização - hipoteticamente, com infinitos dados de treinamento, não precisaríamos de nenhuma regularização, mas no espaço de processamento de imagens é improvável que abordemos essa assíntota). No entanto, isso pode aumentar significativamente o tempo de treinamento e reduzir as taxas de convergência, além de introduzir um conjunto de hiperparâmetros relacionados às técnicas de permutação de imagem de entrada (rotação, corte, dimensionamento, ruído, etc.). Como esse caminho pode aumentar os tempos de treinamento e exigir experimentos adicionais para ajustar os resultados, alguns conselhos gerais seriam obter a melhor precisão da sua rede sem aprimoramento primeiro e, em seguida, verificar se algum aumento modesto produz melhorias. Caso isso aconteça, pode exigir mais experimentação.

Para todo e qualquer experimento de ajuste, é necessário ficar de olho nas mudanças no comportamento de excesso ou de falta de ajuste. A alteração da arquitetura de rede, regimes de treinamento ou hiperparâmetros pode exigir um ajuste adicional da regularização de abandono. A capacidade de determinar prontamente o comportamento excessivo e insuficiente do desempenho do trem / teste é sem dúvida a habilidade de linha de base mais importante no trabalho com NNets, e isso se torna mais intuitivo com a experiência.

Esta é a vela pela qual todos os seus esforços serão guiados. A vela pode apenas iluminar vagamente o caminho, mas sem ela você tropeçará no escuro. Se sua rede estiver com excesso ou falta de ajuste, isso deve ser resolvido antes de tentar permutações aleatórias da estrutura da rede ou hiperparâmetros.

As arquiteturas comparativamente simples com esquemas de treinamento com baunilha incluídas nesta resposta demonstram a realidade de trabalhar com arquiteturas NNET em problemas difíceis como a classificação de imagens: alcançar um resultado "muito bom" com base em abordagens conhecidas por funcionar bem não é difícil, mas a melhoria incremental é cada vez mais caro. A obtenção dos melhores resultados publicados por meio de experimentação vai além das habilidades ou disponibilidade de tempo de muitos (embora seja possível, com tempo e esforço suficientes, seguir as receitas do livro de receitas das abordagens publicadas para replicar seus resultados - mas mesmo isso não é de forma alguma significa trivial). Obter melhorias incrementais a partir de um ponto de partida "muito bom" pode ser um processo muito demorado de tentativa e erro, e muitos experimentos não produzirão nenhuma melhoria significativa.

Isso não pretende dissuadir ninguém de tentar aprender, mas apenas esclarecer que há um investimento significativo necessário para dominar o conjunto de ferramentas (sempre em expansão) no pacote de truques da NNet, e impulsionar melhorias por tentativa e erro pode exigir dezenas (ou centenas) de experimentos ao longo de dias ou semanas de treinamento em GPU dedicado.

O tempo, a habilidade e os recursos (GPU dedicados) necessários para treinar redes com níveis muito altos de desempenho explicam em parte a popularidade das redes pré-treinadas.

T3am5hark
fonte
11
Suas arquiteturas de rede neural não possuem nenhuma camada de pool? isso não cria um número incontrolável de parâmetros?
Spandyie
2
Pooling - pfft! Superestimado. Isso usa uma abordagem totalmente convolucional, que utiliza o esforço para dizimar em vez de agrupar - consulte o documento vinculado para obter uma descrição. O avanço convolucional pode obter o mesmo efeito de "canalização" que o agrupamento por meios ligeiramente diferentes. O fato de ambos trabalharem simplesmente ilustra que não há muito fundamento teórico firme sobre o motivo pelo qual alguma dessas coisas funciona.
T3am5hark
6

Observando os valores de perda e precisão dentro e fora da amostra, seu modelo está com pouca roupa no momento, mas está melhorando monotonicamente. Em outras palavras, parece que executar isso por mais épocas resultaria em maior desempenho preditivo / menos perda de entropia.

Você está usando uma arquitetura altamente regularizada (camadas suspensas), o que não é ruim. No entanto, também não é surpreendente que o treinamento leve muito mais tempo do que sem nenhuma regularização. Devido às camadas de abandono, é improvável que você exagere (substancialmente) em excesso.

Coisas que você pode tentar acelerar o aprendizado:

Eu. ajuste a taxa de aprendizado: por exemplo, comece com uma pequena, suba no meio e, no final, abaixe-a novamente.

ii. adicione normalização do lote : na arquitetura acima, você pode incluir a norma do lote nos blocos convolucionais e nas camadas densas. Geralmente, a camada de norma de lote é adicionada após a ativação não linear, mas antes da interrupção. Não tenho certeza de quão bem a norma de lote é reproduzida com o maxnorm. Para suas camadas densas, eu tentaria lote-norma + desistência com / sem maxnorm. Sinto que você não precisa do maxnorm se aplicar a normalização em lote.

iii. aumentar o tamanho do lote: não sei qual é o tamanho do lote e se você possui uma GPU. Se você possui uma GPU, provavelmente deve tentar maximizar o tamanho do lote em multiplicativos de 32.

Por fim, para garantir que seus dados sejam 'aprendidos' / não corrompidos (por exemplo, você não aplicou uma transformação de má vontade para distorcê-los), eu descartaria toda a regularização da sua arquitetura, executaria o treinamento e verificaria que você pode se ajustar demais ao conjunto de treinamento . Se você pode aprender os dados de treinamento com sucesso, o resto é um exercício de generalização. Se você não conseguir se adaptar demais aos dados de treinamento, mesmo sem regularização, provavelmente seu modelo precisará de mais capacidade (arquitetura mais profunda e mais ampla).

Zhubarb
fonte
Obrigado gentilmente pelo conselho! Você estava certo sobre o MaxNorm interferir levemente. No entanto, mesmo após adicionar as camadas BatchNormalization (consulte a atualização) e remover / incluir o MaxNorm, a precisão ainda é baixa. Nenhum aumento está ocorrendo também. Eu tenho uma GPU e tentei treinar em 64.128.256 e 512 lotes, mas pouca diferença é notada. Em relação à taxa de aprendizado, estou usando o otimizador do Adam e achei que isso deveria ser deixado mais ou menos em paz. No entanto, tentei LR em 0,05, 0,001, 0,0005 e notei que o 0,001 padrão parece melhor ainda. Alguma ideia?
user4779
Também eu sou capaz de me ajustar demais. Eu tentei o meu melhor para copiar a arquitetura nos documentos que parecem conseguir uma precisão de 80% ++ com o MNIST10. Quando deixo o modelo de treinamento por épocas mais longas, parece que a perda agora aumenta (mais de 20 épocas).
user4779
Modificando comentário - na sequência das alterações ao modelo, os gráficos indicam agora que ele está overfitting significativamente os dados (com base na divergência do erro de validação depois de ~ 15 épocas)
T3am5hark
Na verdade, discuto a utilidade dos conselhos oferecidos aqui, especialmente para novos praticantes. Essas são todas as coisas que você pode fazer, com certeza, mas para as pessoas que são novas nas CNNs e não têm a intuição ou o entendimento de como essas coisas funcionam, são muitos botões e alavancas para ajustar sem nenhuma orientação prescritiva além do julgamento cego e erro, improvável que produza resultados positivos. Melhor seria começar primeiro com arquiteturas mais simples, capazes de obter um bom desempenho (não melhor publicado) com um mínimo de ajustes, e depois explorar caminhos de melhoria a partir daí. Meus dois centavos.
T3am5hark
Para elaborar ainda mais - não brinque com as taxas de aprendizado, use Adam. Ele superará o ajuste manual das taxas de aprendizado em 99,99% do tempo. Além disso - a afirmação de que "é improvável que você se ajuste demais" está totalmente errada (como indicado pelos gráficos de acompanhamento que agora demonstram um ajuste excessivo significativo), e não há boas razões para o pôster assumir que ... não há nada a dizer a priori para uma determinada arquitetura se uma determinada taxa de abandono será regularizada o suficiente para evitar ajustes excessivos.
T3am5hark
1

Eu dei uma chance hoje e consegui atingir quase 75-80% em precisão de teste.

Histórico de treinamento

  • O número total de parâmetros utilizados foi: 183,242

  • Você pode fazer melhor adicionando talvez mais algumas camadas, mas não precisa ser excessivo. Redes mais complexas nem sempre resultam em melhores resultados.

Sugestões

Minha sugestão é que você mantenha sua arquitetura simples. Siga a Navalha de Occam , simples é melhor.

  • Escale seus dados

  • Não use uma semente aleatória

  • Use um otimizador apropriado; Eu usei Adadelta como é de Keras.

  • CNNs não precisam ser complicadas; mantenha simples

  • Redes mais finas e magras às vezes funcionam melhor que redes mais amplas

  • Use regularização (por exemplo, desistência)

Abaixo está o meu código (usando o 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
fonte