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:
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:
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)
Respostas:
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/width 2/heightwidth n n/heightwidth height∗width os 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:
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
SGD
otimizador simples com valores padrão?Assim, você pode fazer várias otimizações:
LinearRegression
com o scikit-learn. OK, isso não é o que você deseja, mas eu apenas quero ilustrar o quão complexo é esse modelo.Dense
camadas ocultasSGD
otimizador padrãosigmoid
ativação. Você pode pensar em cada um dos nós da camada oculta como detectar se um quadrado está em um determinado local.Ps
Eu acho que você vai gostar deste post de Adit Deshpande.
fonte
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.
fonte
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.
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.
fonte
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.
fonte