Por que a perda / precisão flutua durante o treinamento? (Keras, LSTM)

11

Eu uso a rede LSTM em Keras. Durante o treinamento, a perda varia muito, e eu não entendo por que isso aconteceria.

Aqui está o NN que eu estava usando inicialmente: insira a descrição da imagem aqui

E aqui estão a perda e a precisão durante o treinamento: insira a descrição da imagem aqui

(Observe que a precisão chega a 100% eventualmente, mas são necessárias cerca de 800 épocas.)

Eu pensei que essas flutuações ocorrem por causa das camadas / alterações do Dropout na taxa de aprendizado (usei rmsprop / adam), então criei um modelo mais simples: insira a descrição da imagem aqui

Eu também usei SGD sem impulso e decadência. Eu tentei valores diferentes para, lrmas ainda obtive o mesmo resultado.

sgd = optimizers.SGD(lr=0.001, momentum=0.0, decay=0.0, nesterov=False)

Mas eu ainda tinha o mesmo problema: a perda flutuava em vez de apenas diminuir. Eu sempre pensei que a perda deveria diminuir gradualmente, mas aqui não parece se comportar assim.

Assim:

  1. É normal que a perda flutue assim durante o treinamento? E por que isso aconteceria?

  2. Caso contrário, por que isso aconteceria no modelo LSTM simples com o lrparâmetro definido com algum valor realmente pequeno?

Obrigado. Observe que verifiquei perguntas semelhantes aqui, mas isso não me ajudou a resolver meu problema.

Atualização: perda para mais de 1000 épocas (sem camada BatchNormalization, o modificador RmsProp de Keras): insira a descrição da imagem aqui

Upd. 2: Para o gráfico final:

model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])
history = model.fit(train_x, train_y, epochs = 1500)

Dados: sequências de valores da corrente (dos sensores de um robô).

Variáveis ​​alvo: a superfície na qual o robô está operando (como um vetor quente, 6 categorias diferentes).

Pré-processando:

  1. alterou a frequência de amostragem para que as seqüências não sejam muito longas (o LSTM não parece aprender de outra forma);
  2. recorte as seqüências nas seqüências menores (o mesmo comprimento para todas as seqüências menores: 100 timesteps cada);
  3. verifique se cada uma das 6 classes tem aproximadamente o mesmo número de exemplos no conjunto de treinamento.

Sem preenchimento.

Forma do conjunto de treinamento (# sequências, #timesteps em uma sequência, #features):

(98, 100, 1) 

Forma dos rótulos correspondentes (como um vetor quente para 6 categorias):

(98, 6)

Camadas:

insira a descrição da imagem aqui

O restante dos parâmetros (taxa de aprendizado, tamanho do lote) são os mesmos que os padrões do Keras:

keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)

batch_size: Inteiro ou Nenhum. Número de amostras por atualização de gradiente. Se não especificado, o padrão será 32.

Upd. 3: A perda para batch_size=4:

insira a descrição da imagem aqui

Para batch_size=2o LSTM, parece não ter aprendido adequadamente (a perda varia em torno do mesmo valor e não diminui).

Upd. 4: Para verificar se o problema não é apenas um bug no código: Fiz um exemplo artificial (2 classes que não são difíceis de classificar: cos vs arccos). Perda e precisão durante o treinamento para estes exemplos: insira a descrição da imagem aqui

valeria
fonte
Que tal apresentar seu problema adequadamente (qual é a pergunta de pesquisa que você está tentando responder, descreva seus dados, mostre seu modelo etc.)? Você só nos mostrar suas camadas, mas não sabemos nada sobre os dados, o pré-processamento, a função de perda, o tamanho do lote, e muitos outros detalhes que podem influenciar o resultado
DeltaIV
11
Outras coisas que podem afetar a estabilidade são triagem, embaralhamento, preenchimento e todos os truques sujos necessários para obter RNNs treinados em mini-lotes para trabalhar com sequências de comprimento amplamente variável. Os picos enormes que você atinge em cerca de 1200 épocas me lembram um caso em que eu tive que lidar exatamente com isso. Quem sabe, talvez a atenção é tudo que você precisa
DeltaIV
11
Eu sei que é loucura. É exatamente por isso que estou aqui: entender por que é assim / como possivelmente corrigi-lo.
Valeria
11
1. O robô tem muitos sensores, mas eu apenas uso as medições de corrente.
Valeria

Respostas:

4

Existem várias razões que podem causar flutuações na perda de treinamento ao longo das épocas. A principal delas é o fato de que quase todas as redes neurais são treinadas com diferentes formas de gradiente estocástico decente . É por isso que existe o parâmetro batch_size que determina quantas amostras você deseja usar para fazer uma atualização nos parâmetros do modelo. Se você usar todas as amostras para cada atualização, deverá vê-la diminuindo e finalmente atingindo um limite. Observe que existem outras razões para a perda ter algum comportamento estocástico.

Isso explica por que vemos oscilações. Mas no seu caso, é mais do que normal, eu diria. Olhando para o seu código, vejo duas fontes possíveis.

  1. Rede grande, conjunto de dados pequeno: parece que você está treinando uma rede relativamente grande com parâmetros de mais de 200K com um número muito pequeno de amostras, ~ 100. Para colocar isso em perspectiva, você deseja aprender parâmetros de 200K ou encontrar um bom mínimo local em um espaço de 200K-D usando apenas 100 amostras. Assim, você pode acabar andando por aí em vez de se prender a um bom mínimo local. (A perambulação também se deve ao segundo motivo abaixo).

  2. Muito pequeno batch_size. Você usa batch_size muito pequeno. Portanto, é como se você estivesse confiando em cada pequena parte dos pontos de dados. Digamos que, dentro dos seus pontos de dados, você tenha uma amostra incorreta. Essa amostra, quando combinada com 2 a 3 amostras mesmo rotuladas adequadamente, pode resultar em uma atualização que não diminui a perda global, mas aumenta ou a joga fora de um mínimo local. Quando o batch_size for maior, esses efeitos serão reduzidos. Juntamente com outros motivos, é bom ter batch_size maior que o mínimo. Tê-lo muito grande também tornaria o treinamento lento. Portanto, batch_size é tratado como um hiperparâmetro.

SaTa
fonte
0

Sua curva de perda não parece tão ruim para mim. Definitivamente, deve "flutuar" para cima e para baixo um pouco, desde que a tendência geral seja de que esteja caindo - isso faz sentido.

O tamanho do lote também ajudará na aprendizagem da sua rede; portanto, você pode otimizar isso junto com a sua taxa de aprendizado. Além disso, eu traçaria a curva inteira (até atingir 100% de precisão / perda mínima). Parece que você o treinou por 800 épocas e está mostrando apenas as primeiras 50 épocas - toda a curva provavelmente dará uma história muito diferente.

Anthony Gatti
fonte
Você está certo. Além disso, depois de executar novamente o treinamento, ele fica ainda menos estável do que era, então tenho quase certeza de que estou perdendo algum erro. Atualizei a postagem com o treinamento para mais de 1000 épocas.
Valeria
0

As flutuações são normais dentro de certos limites e dependem do fato de você usar um método heurístico, mas no seu caso elas são excessivas. Apesar de todo o desempenho ter uma direção definida, o sistema funciona. Nos gráficos que você publicou, o problema depende dos seus dados, por isso é um treinamento difícil. Se você já tentou alterar a taxa de aprendizado, tente alterar o algoritmo de treinamento. Você concorda em testar seus dados: primeiro calcule a taxa de erro de Bayes usando um KNN (use a regressão de truque, se necessário), dessa forma, você pode verificar se os dados de entrada contêm todas as informações necessárias. Em seguida, tente o LSTM sem a validação ou desistência para verificar se ele tem a capacidade de alcançar o resultado necessário. Se o algoritmo de treinamento não for adequado, você deverá ter os mesmos problemas, mesmo sem a validação ou desistência. No final, ajuste o treinamento e o tamanho da validação para obter o melhor resultado no conjunto de testes. A teoria da aprendizagem estatística não é um tópico que possa ser discutido ao mesmo tempo; devemos prosseguir passo a passo.

Emiliano Rosso
fonte