Treinar uma rede neural para regressão sempre prediz a média

9

Estou treinando uma rede neural convolucional simples para regressão, onde a tarefa é prever a localização (x, y) de uma caixa em uma imagem, por exemplo:

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui

A saída da rede possui dois nós, um para x e um para y. O restante da rede é uma rede neural convolucional padrão. A perda é um erro quadrático médio padrão entre a posição prevista da caixa e a posição de verdade do solo. Estou treinando em 10000 dessas imagens e validando em 2000.

O problema que estou tendo é que, mesmo após um treinamento significativo, a perda não diminui realmente. Depois de observar a saída da rede, percebo que a rede tende a emitir valores próximos a zero, para os dois nós de saída. Como tal, a previsão da localização da caixa é sempre o centro da imagem. Há algum desvio nas previsões, mas sempre em torno de zero. Abaixo mostra a perda:

insira a descrição da imagem aqui

Eu executei isso por muito mais épocas do que as mostradas neste gráfico, e a perda ainda nunca diminui. Curiosamente aqui, a perda realmente aumenta em um ponto.

Portanto, parece que a rede está apenas prevendo a média dos dados de treinamento, em vez de aprender um bom ajuste. Alguma idéia de por que isso pode ser? Estou usando Adam como otimizador, com uma taxa de aprendizado inicial de 0,01 e relus como ativações


Se você está interessado em alguns dos meus códigos (Keras), está abaixo:

# 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)
Karnivaurus
fonte
As imagens estão nos principais exemplos de suas amostras reais? São 5 amostras separadas? Parece não haver informações nas imagens que ajudem a generalizar. Quero dizer, você não precisa de uma rede neural para encontrar a localização x, y do quadrado branco, basta analisar a imagem e procurar um pixel branco. Explique um pouco mais sobre sua visão para este modelo. Existe algum padrão temporal em que você está prevendo o próximo local?
Phot
Olá, e sim, as imagens são 5 amostras separadas. Não tenho certeza de como elas são renderizadas para você, mas devem ter 5 imagens quadradas individuais (alterei um pouco o layout para ajudar ...). Sim, percebo que você não precisa de uma rede neural para esta tarefa, mas é apenas um experimento de teste para me ajudar a aprender como fazer a regressão com uma rede neural. Não entendo o que você quer dizer com não haver informações para ajudar a generalizar ... Cada par de treinamento consiste em uma imagem quadrada e um vetor bidimensional da localização (x, y) do quadrado. Obrigado :)
Karnivaurus
11
1) Seu formato de entrada na primeira camada de conv está usando 3 canais (rbg), mas seus dados são em escala de cinza (1 canal) 2) Você não precisa de muitas camadas e filtros de conv. Na verdade, acho que uma única camada e um punhado de pequenos grãos vai ficar bem.
Phot
Você tem certeza de que as imagens realmente correspondem aos alvos?
user31264
11
Como o @photox diz, você não precisa das camadas de conv. A adição destes torna mais difícil para o otimizador encontrar uma boa solução. Se você remover as 3 camadas de conv, suspeito que seu "modelo" funcione.
Pieter

Respostas:

9

O otimizador não pode convergir para uma solução (sub) ideal. Por quê? Seu problema é muito fácil e / ou seu modelo é muito complexo.

Problema fácil demais

Como o @photox já disse, esse problema pode ser resolvido com apenas uma única camada oculta. Eu até suspeito que isso possa ser feito sem uma camada oculta. Isso ocorre porque esse problema é linear separadamente .

Deixe-me ilustrar isso. Imagine uma rede neural sem camadas ocultas e uma função de ativação linear (você também pode chamar de regressão linear). Para calcular a localização x do quadrado, cada pixel é conectado à saída x. A primeira coluna de pixels está conectada ao peso . A segunda coluna está conectada ao peso . Isso continua até a última coluna (por exemplo, coluna ) que está conectada com o peso . Desde2 / altura largura n n / altura largura altura largura1/height/width2/heightwidthnn/heightwidthheightwidthos pixels são diferentes de zero (por exemplo, o viés é igual ao valor da cor cinza); a ativação da saída x é igual ao centro do quadrado. Portanto, uma função linear pode calcular a localização do quadrado.

Existem várias soluções:

  • Escolha um problema mais difícil, por exemplo, classificação da imagem
  • Adicione ruído, por exemplo, sal e pimenta ou ruído branco
  • Torne o problema mais difícil, por exemplo, prevendo a localização de um quadrado vermelho enquanto houver muitos círculos de cores diferentes no fundo

Modelo muito complexo

Seu modelo possui algumas partes que adicionam muita complexidade, sem ajudar o otimizador a encontrar um ótimo ideal.

Por exemplo, as camadas convolucionais. A primeira camada possui 32 filtros convolucionais de tamanho . O que você espera que esses filtros aprendam? Na classificação de imagens, esses filtros aprendem a detectar arestas, cantos, gradientes e blobs. Mas, neste caso, existem apenas alguns filtros que fazem sentido. Eu posso pensar em arestas da esquerda para a direita e vice-versa e de cima para baixo e vice-versa. No seu caso, existem aproximadamente 28 filtros que adicionam ruído aleatório. A exclusão dessas (ou apenas de toda a camada) torna muito mais fácil para o otimizador encontrar um ótimo que funcione.5×5

Outro exemplo é o otimizador Adam, com muitos parâmetros extras. O otimizador do Adam pode funcionar bem com esses parâmetros, mas por que você não começa com um SGDotimizador simples com valores padrão?

Assim, você pode fazer várias otimizações:

  • use LinearRegressioncom o scikit-learn. OK, isso não é o que você deseja, mas eu apenas quero ilustrar o quão complexo é esse modelo.
  • Remova as camadas de conv.
  • Diminuir o tamanho das Densecamadas ocultas
  • Use o SGDotimizador padrão
  • Se você estiver usando uma camada oculta, tente uma sigmoidativação. Você pode pensar em cada um dos nós da camada oculta como detectar se um quadrado está em um determinado local.
  • Se tudo isso não funcionar, experimente um pouco a taxa de aprendizado para descobrir se está muito alta ou muito baixa.

Ps

Eu acho que você vai gostar deste post de Adit Deshpande.

Pieter
fonte
Deixe-me saber se essas soluções mudaram o comportamento dos otimizadores.
Pieter
Obrigado, isso é muito útil. Estou trabalhando para tentar suas sugestões. No entanto, eu não entendo o seu primeiro ponto. Estou confuso sobre o porquê, se o problema é muito simples, é mais difícil otimizar do que um problema mais complexo. Para uma determinada rede, por que um problema mais simples seria mais difícil de otimizar do que um problema mais complexo? Em um problema simples, eu pensaria que haveria gradientes muito fortes e uma ótima otimização global. Mas o seu primeiro ponto diz que a simplicidade do problema torna a otimização duro, sugerindo que um problema mais complexo ajudaria a otimização ...
Karnivaurus
0

Parece um problema típico de super adaptação. Seus dados não fornecem informações suficientes para obter o melhor resultado. Você escolhe o NN complexo com o qual treina para lembrar todas as nuances dos dados do trem . A perda nunca pode ser zero, como no seu gráfico. BTW Parece que sua validação tem um bug ou um conjunto de validação não é bom para validação porque a perda de validação também está ficando zero.

Leonid Ganeline
fonte
4
A pergunta diz que a rede quase sempre gera zero. Esse seria um caso de falta de adequação grave , não adequação excessiva . Também não há diferença entre a formação eo erro de validação na curva de aprendizagem, indicando que overfitting não é o problema (o erro não é zero, a escala é logarítmica)
user20160
0

Estou enfrentando o mesmo problema com meu conjunto de dados. Acontece que, no meu caso, os preditores estão altamente concentrados com uma variação muito pequena. Você deve verificar a variação de suas variáveis ​​de previsão e ver como elas são distribuídas.Distribuição da variável que estou tentando prever

No entanto, algumas transformações na variável de saída podem ser executadas para modificar ou alterar sua escala. Isso pode resultar em uma distribuição de tipo mais uniforme. Por exemplo, nas tarefas de reconhecimento de imagem, a equalização do histograma ou o aprimoramento do contraste às vezes funcionam a favor da tomada de decisão correta.

Ravi Shankar
fonte
-1

Na verdade, eu estava trabalhando em um problema muito semelhante. Basicamente, eu tinha vários pontos em um fundo branco e estava treinando um NN para reconhecer o ponto que foi colocado primeiro no fundo. O jeito que eu descobri trabalhar era usar apenas uma camada de neurônios totalmente conectada (um NN de uma camada). Por exemplo, para uma imagem 100x100, eu teria 10.000 neurônios de entrada (os pixels) conectados diretamente a 2 neurônios de saída (as coordenadas). No PyTorch, quando converti os valores de pixel em um tensor, ele normalizava meus dados automaticamente, subtraindo a média e dividindo pelo desvio padrão. Em problemas normais de aprendizado de máquina, isso é bom, mas não para uma imagem em que possa haver uma disparidade no número de pixels coloridos em uma imagem (ou seja, na sua, onde existem apenas alguns pixels brancos). Então, Normalizei manualmente dividindo todos os valores de intensidade de pixel por 255 (então eles estão agora no intervalo de 0 a 1 sem a técnica de normalização típica que tenta ajustar todos os valores de intensidade a uma distribuição normal). Então, eu ainda tinha problemas porque estava prevendo a coordenada média dos pixels no conjunto de treinamento. Portanto, minha solução foi definir uma taxa de aprendizado muito alta, o que contraria quase todos os instrutores e tutoriais de ML. Em vez de usar 1e-3, 1e-4, 1e-5, como a maioria das pessoas diz, eu estava usando uma taxa de aprendizado de 1 ou 0,1 com descida de gradiente estocástico. Isso corrigiu meus problemas e minha rede finalmente aprendeu a memorizar meu conjunto de treinamento. Não generaliza muito bem para um conjunto de testes, mas pelo menos funciona um pouco, o que é uma solução melhor do que a maioria das pessoas sugeriu na sua pergunta. agora, no intervalo de 0 a 1, sem a técnica de normalização típica que tenta ajustar todos os valores de intensidade a uma distribuição normal). Então, eu ainda tinha problemas porque estava prevendo a coordenada média dos pixels no conjunto de treinamento. Portanto, minha solução foi definir uma taxa de aprendizado muito alta, o que contraria quase todos os instrutores e tutoriais de ML. Em vez de usar 1e-3, 1e-4, 1e-5, como a maioria das pessoas diz, eu estava usando uma taxa de aprendizado de 1 ou 0,1 com descida de gradiente estocástico. Isso corrigiu meus problemas e minha rede finalmente aprendeu a memorizar meu conjunto de treinamento. Não generaliza muito bem para um conjunto de testes, mas pelo menos funciona um pouco, o que é uma solução melhor do que a maioria das pessoas sugeriu na sua pergunta. agora, no intervalo de 0 a 1, sem a técnica de normalização típica que tenta ajustar todos os valores de intensidade a uma distribuição normal). Então, eu ainda tinha problemas porque estava prevendo a coordenada média dos pixels no conjunto de treinamento. Portanto, minha solução foi definir uma taxa de aprendizado muito alta, o que contraria quase todos os instrutores e tutoriais de ML. Em vez de usar 1e-3, 1e-4, 1e-5, como a maioria das pessoas diz, eu estava usando uma taxa de aprendizado de 1 ou 0,1 com descida de gradiente estocástico. Isso corrigiu meus problemas e minha rede finalmente aprendeu a memorizar meu conjunto de treinamento. Não generaliza muito bem para um conjunto de testes, mas pelo menos funciona um pouco, o que é uma solução melhor do que a maioria das pessoas sugeriu na sua pergunta.

Prumo
fonte