Regressão linear simples em Keras

11

Depois de analisar esta pergunta: tentando imitar a regressão linear usando Keras , tentei dar meu próprio exemplo, apenas para fins de estudo e para desenvolver minha intuição.

Baixei um conjunto de dados simples e usei uma coluna para prever outra. Os dados são assim:

dados de televisão

Agora, criei um modelo keras simples com uma camada linear de um nó e comecei a executar descida de gradiente nela:

from keras.layers import Input, Dense
from keras.models import Model

inputs = Input(shape=(1,))
preds = Dense(1,activation='linear')(inputs)

model = Model(inputs=inputs,outputs=preds)
sgd=keras.optimizers.SGD()
model.compile(optimizer=sgd ,loss='mse',metrics=['mse'])
model.fit(x,y, batch_size=1, epochs=30, shuffle=False)

A execução do modelo assim me dá nanperdas em todas as épocas.

Link para o notebook jupyter

Então, decidi começar a experimentar coisas e só consigo um modelo decente se usar uma taxa de aprendizado ridiculamente pequena sgd=keras.optimizers.SGD(lr=0.0000001) :

equipado com dados de televisão

Agora, por que isso está acontecendo? Terei que ajustar manualmente a taxa de aprendizado dessa maneira para cada problema que enfrentar? Estou fazendo algo errado aqui? Este deveria ser o problema mais simples possível, certo?

Obrigado!

Felipe Almeida
fonte

Respostas:

11

Provavelmente porque não houve normalização . As redes neurais são muito sensíveis a dados não normalizados.

Alguma intuição: quando tentamos encontrar nosso mínimo global multidimensional (como no modelo descendente de gradiente estocástico), em cada iteração cada recurso "puxa" para sua dimensão (direção do vetor) com alguma força (o comprimento do vetor ) Quando os dados não são normalizados, um pequeno passo no valor da coluna A pode causar uma grande mudança na coluna B.

Seu código lidou com isso usando sua taxa de aprendizado muito baixa, que "normalizou" o efeito em todas as colunas, mas causou um processo de aprendizado atrasado, exigindo muito mais épocas para concluir.

Adicione este código de normalização:

from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
x = sc.fit_transform(x)
y = sc.fit_transform(y)

E simplesmente reduza o parâmetro da taxa de aprendizado (lr) - deixando escolher sabiamente um valor automático para você. Eu tenho o mesmo gráfico desejado como você agora :)

mork
fonte
Parece arrumado ... a única coisa que eu não gosto é que precisarei aplicar essa padronização de maneira semelhante para testar entradas e, em seguida, a saída que obtiver também estará em outro conjunto de unidades.
Felipe Almeida
2
Isso mesmo, @Felipe Almeida, o resultado da saída deve ser "revertido", mas isso geralmente é incorporado nas bibliotecas. Dê uma olhada em inverse_transform scikit-learn.org/stable/modules/generated/... e alguns outros métodos de pré-processamento scikit-learn.org/stable/modules/preprocessing.html
Mork
2

A normalização é mais importante quando você tem mais de uma variável dependente. Se você observar o gráfico de dispersão, poderá ver valores discrepantes. Uma rede neural sem camadas ocultas é igual a um modelo de regressão linear. Assim, está ajustando a melhor linha para minimizar a distância dos resíduos. Remova os outliers e parecerá mais apropriado.

Samuel Sherman
fonte