Sobreajuste de redes neurais convolucionais. A desistência não está ajudando

16

Estou brincando um pouco com convnets. Especificamente, estou usando o conjunto de dados kaggle gatos contra cães, que consiste em 25000 imagens rotuladas como gato ou cachorro (12500 cada).

Consegui atingir cerca de 85% de precisão de classificação no meu conjunto de testes, no entanto, estabeleci uma meta de atingir 90% de precisão.

Meu principal problema é o excesso de ajustes. De alguma forma, sempre acaba acontecendo (normalmente após a época 8-10). A arquitetura da minha rede é pouco inspirada no VGG-16, mais especificamente, minhas imagens são redimensionadas para 128x128x3 e, em seguida, corro:

Convolution 1 128x128x32 (kernel size is 3, strides is 1)
Convolution 2 128x128x32 (kernel size is 3, strides is 1)
Max pool    1 64x64x32   (kernel size is 2, strides is 2)
Convolution 3 64x64x64   (kernel size is 3, strides is 1)
Convolution 4 64x64x64   (kernel size is 3, strides is 1)
Max pool    2 32x32x64   (kernel size is 2, strides is 2)
Convolution 5 16x16x128  (kernel size is 3, strides is 1)
Convolution 6 16x16x128  (kernel size is 3, strides is 1)
Max pool    3 8x8x128    (kernel size is 2, strides is 2)
Convolution 7 8x8x256    (kernel size is 3, strides is 1)
Max pool    4 4x4x256    (kernel size is 2, strides is 2)
Convolution 8 4x4x512    (kernel size is 3, strides is 1)
Fully connected layer 1024 (dropout 0.5)
Fully connected layer 1024 (dropout 0.5)

Todas as camadas, exceto a última, têm relus como funções de ativação.

Observe que eu tentei combinações diferentes de convoluções (comecei com convoluções mais simples).

Além disso, aumentei o conjunto de dados espelhando as imagens, para que, no total, eu tivesse 50000 imagens.

Além disso, estou normalizando as imagens usando a normalização min max, onde X é a imagem

X=X-0 0/255-0 0

O código é escrito em tensorflow e os tamanhos de lote são 128.

Os mini-lotes de dados de treinamento acabam se ajustando demais e com precisão de 100%, enquanto os dados de validação parecem parar de aprender em torno de 84 a 85%.

Eu também tentei aumentar / diminuir a taxa de desistência.

O otimizador usado é o AdamOptimizer com uma taxa de aprendizado de 0,0001

No momento, estou jogando com esse problema nas últimas 3 semanas e 85% parecem ter colocado uma barreira na minha frente.

Para que conste, sei que poderia usar o aprendizado por transferência para obter resultados muito mais altos, mas sou interessante em construir essa rede como uma experiência de auto-aprendizado.

Atualizar:

Estou executando a mesma rede com um tamanho de lote diferente; nesse caso, estou usando um tamanho de lote muito menor (16 em vez de 128) até agora, estou atingindo uma precisão de 87,5% (em vez de 85%). Dito isto, a rede acaba se ajustando de qualquer maneira. Ainda não entendo como um abandono de 50% das unidades não está ajudando ... obviamente estou fazendo algo errado aqui. Alguma ideia?

Atualização 2:

Parece que o problema tinha a ver com o tamanho do lote, como com um tamanho menor (16 em vez de 128), agora estou alcançando uma precisão de 92,8% no meu conjunto de testes, com o tamanho menor do lote em que a rede ainda se adapta (os mini lotes acabam com uma precisão de 100%), no entanto, a perda (erro) continua diminuindo e, em geral, é mais estável. Os contras são um tempo de execução MUITO mais lento, mas vale totalmente a pena a espera.

Juan Antonio Moriano, Gomez
fonte
2
Você poderia dar mais detalhes sobre sua avaliação de excesso de ajuste? Por exemplo, a precisão da validação diminui a qualquer momento, juntamente com a divergência dos resultados de treinamento e validação? Como sobre a função de perda?
Neil Slater
Boa pergunta, então, sobreajuste, quero dizer o fato de que os mini-lotes em trem alcançam precisão de 100% e perdas de 0,08, enquanto a validação parece nunca cair abaixo de 0,35 e sua precisão permanece agora em 88%. De acordo com a validação, ela não parece cair (pelo menos não muito), parece ficar plana. No entanto, como o mini lote consegue uma perda tão baixa enquanto a validação ainda está longe disso?
Juan Antonio Gomez Moriano
Não sei uma resposta para você, no entanto, esse comportamento - grande divergência entre trem e validação, mas ainda validação de platô OK - é algo que já vi antes algumas vezes. Eu quase hesito em chamá-lo de excessivo, porque às vezes os resultados do teste são aceitáveis.
Neil Slater
"Ainda não entendo como um abandono de 50% das unidades não está ajudando". Vi pessoas usando valores muito mais altos de abandono com sucesso.
Ricardo Cruz

Respostas:

14

Ok, depois de muita experimentação eu consegui obter alguns resultados / idéias.

Em primeiro lugar, tudo sendo igual, lotes menores no conjunto de treinamento ajudam muito para aumentar o desempenho geral da rede, como um lado negativo, o processo de treinamento é muuuuuch mais lento.

Segundo ponto, os dados são importantes, nada de novo aqui, mas como aprendi ao combater esse problema, mais dados sempre parecem ajudar um pouco.

Terceiro ponto, o abandono é útil em grandes redes com muitos dados e muitas iterações. Na minha rede, apliquei o abandono apenas nas camadas finais totalmente conectadas, as camadas de convolução não foram aplicadas.

Quarto ponto (e isso é algo que estou aprendendo várias vezes): as redes neurais exigem MUITO para treinar, mesmo em boas GPUs (eu treinei essa rede no floydhub, que usa placas NVIDIA bastante caras), então PATIENCE é a chave .

Conclusão final: os tamanhos dos lotes são mais importantes do que se pensa, aparentemente é mais fácil atingir um mínimo local quando os lotes são maiores.

O código que escrevi está disponível como um notebook python, acho que está decentemente documentado

https://github.com/moriano/loco-learning/blob/master/cats-vs-dogs/cats-vs-dogs.ipynb

Juan Antonio Moriano, Gomez
fonte
Obrigado por postar suas descobertas. Pergunta rápida: Eu estou enfrentando um problema semelhante e eu vi isso no notebook que você postou: NOTE USE EITHER mean centering or min-max, NOT BOTH. Atualmente, estou dividindo minhas imagens de entrada por 255 na minha input_fn(API do Tensorflow Estimator). Então, dentro do modelo, estou executando essa entrada através da norma de lote. Ainda devo fazer apenas uma dessas normalizações? Veja github.com/formigone/tf-imagenet/blob/master/models/…
rodrigo-silveira
Meu entendimento é que a divisão por 255 é feita apenas uma vez para cada imagem, e o motivo é manter todos os valores entre 0 e 1, pois isso fornecerá estabilidade numérica.
Juan Antonio Gomez Moriano
Claro, eu entendi. Mas você acha que faz sentido também normalizar em lote esses valores no intervalo [0, 1]?
Rodrigo-silveira
Isso, eu não sei, tem sido um tempo desde que eu usei normalização lote :)
Juan Antonio Gomez Moriano
3

Sugiro que você analise os gráficos de aprendizado de sua precisão de validação, como sugeriu Neil Slater. Em seguida, se a queda na precisão da validação tentar reduzir o tamanho da sua rede (parece muito profunda), adicione a interrupção às camadas CONV e BatchNormalization após cada camada. Pode ajudar a se livrar do excesso de ajustes e aumentar a precisão do teste.

HatemB
fonte
Obrigado pelo conselho, experimente, fiquei, no entanto, com a impressão de que as camadas CONV não exigem desistência, na maioria dos papéis que li, a desistência parece ser aplicada sempre nas camadas totalmente conectadas, e não nas convolutinas.
Juan Antonio Gomez Moriano
3

Existem várias soluções possíveis para o seu problema.

  1. Use o Dropout nas camadas anteriores (camadas convolucionais) também.

  2. Sua rede parece bastante grande para uma tarefa "fácil"; tente reduzi-lo. As grandes arquiteturas também são treinadas em conjuntos de dados muito maiores.

Se você deseja manter sua arquitetura "grande", tente:

  1. Ampliação da imagem para aumentar virtualmente seus dados de treinamento

  2. Tente treinamento adversário. Às vezes ajuda.

Andreas Look
fonte
"Sua rede parece bastante grande para uma tarefa tão" fácil "; tente reduzi-la. As grandes arquiteturas também são treinadas em conjuntos de dados muito maiores." Discordo, à medida que adicionei mais convoluções, a precisão aumentou (inicialmente eu estava atingindo 68% com apenas duas convoluções). Além disso, já estou aumentando meu conjunto de dados, opero com 50000 imagens.
Juan Antonio Gomez Moriano
2

Uma coisa que ainda não foi mencionada e que você pode considerar para o futuro: você ainda pode aumentar sua desistência nas camadas totalmente conectadas.

Li um jornal uma vez que usava 90% de desistência. Embora tivesse muitos nós (2048, se bem me lembro), tentei isso sozinho em camadas com menos nós e foi muito útil em alguns casos.

Eu apenas procurei qual era o papel. Não me lembro de qual papel acabei de lembrar, mas encontrei aqueles que também tiveram algum sucesso com taxas de abandono de 90%.

Karpathy, A., Toderici, G., Shetty, S., Leung, T., Sukthankar, R., & Fei-Fei, L. (2014). Classificação de vídeo em larga escala com redes neurais convolucionais. Em Anais da conferência IEEE sobre Visão Computacional e Reconhecimento de Padrões (pp. 1725-1732).

Simonyan, K. & Zisserman, A. (2014). Redes convolucionais de dois fluxos para reconhecimento de ações em vídeos. In Advances in neural information processing systems (pp. 568-576).

Varol, G., Laptev, I., & Schmid, C. (2017). Convoluções temporais de longo prazo para reconhecimento de ações. Transações IEEE em análise de padrões e inteligência de máquina.

Kefbach
fonte
0

Eu tive esse problema também. Depois de mexer com ele por horas, por acaso decidi embaralhar os dados antes de inseri-los no sistema e pronto, ele começou a funcionar. Demorei um pouco para descobrir que foi o embaralhamento que fez o truque! Espero que isso salve alguém da frustração!

user79129
fonte