Como transformar entradas e extrair saídas úteis em uma rede neural?

9

Então, eu tenho tentado entender as redes neurais desde que me deparei com o blog de Adam Geitgey sobre aprendizado de máquina. Eu li o máximo que posso sobre o assunto (que eu posso entender) e acredito que entendo todos os conceitos amplos e alguns dos trabalhos (apesar de serem muito fracos em matemática), neurônios, sinapses, pesos, funções de custo, retropropagação etc. No entanto, não consegui descobrir como traduzir problemas do mundo real em uma solução de rede neural.

Caso em questão, Adam Geitgey fornece como exemplo de uso, um sistema de previsão de preços da habitação, onde um conjunto de dados contém o número de quartos , Sq. pés , bairro e preço de venda, você pode treinar uma rede neural para poder prever o preço de uma casa. No entanto, ele não consegue implementar uma possível solução no código. O mais próximo que ele chega, a título de exemplo, é uma função básica que demonstra como você implementaria pesos:

def estimate_house_sales_price(num_of_bedrooms, sqft, neighborhood):
  price = 0

  # a little pinch of this
  price += num_of_bedrooms * 1.0

  # and a big pinch of that
  price += sqft * 1.0

  # maybe a handful of this
  price += neighborhood * 1.0

  # and finally, just a little extra salt for good measure
  price += 1.0

  return price 

Outros recursos parecem se concentrar mais na matemática e no único exemplo de código básico que eu pude entender (isto é, que nem todos cantam, todos base de código de classificação de imagens dançantes) é uma implementação que treina uma rede neural para ser um XOR portão que lida apenas com 1 e 0.

Portanto, há uma lacuna no meu conhecimento que eu simplesmente não consigo preencher. Se voltarmos ao problema de previsão de preços da habitação , como tornar os dados adequados para alimentar uma rede neural? Por exemplo:

  • Nº de quartos: 3
  • Sq. pés: 2000
  • Bairro: Normaltown
  • Preço de venda: $ 250,000

Você pode apenas alimentar 3 e 2000 diretamente na rede neural porque são números? Ou você precisa transformá-los em outra coisa? Da mesma forma, e o valor Normaltown , que é uma string, como você o traduz em um valor que uma rede neural possa entender? Você pode simplesmente escolher um número, como um índice, desde que consistente nos dados?

Muitos dos exemplos de redes neurais que vi nos números que passam entre as camadas são de 0 a 1 ou -1 a 1. Portanto, no final do processamento, como você transforma o valor de saída em algo útil como $ 185.000 ?

Sei que o exemplo de previsão de preços da habitação provavelmente não é um problema particularmente útil, uma vez que foi simplificado demais para apenas três pontos de dados. Mas eu sinto que, se eu pudesse superar esse obstáculo e escrever um aplicativo extremamente básico que treine usando dados pseudo-reais e cuspa uma resposta pseudo-real, então eu vou quebrar a parte de trás e ser capaz de chutar e aprofundar-se no aprendizado de máquina.

David
fonte

Respostas:

10

Essa é uma boa pergunta que lutei comigo mesmo ao tentar codificar uma RNA.

Abaixo está uma boa solução de uso geral, e eu implementei no meu código para tentar prever dados numéricos bem comportados. Se seus dados não forem bem comportados (por exemplo, repletos de discrepantes), talvez seja necessário fazer mais trabalho para normalizar as entradas e saídas. Alguns dos métodos mais avançados são descritos aqui .

Nota: Assumirei que você está usando f (x) = tanh (x) como sua função de ativação. Se não estiver, você ainda deve ser capaz de pensar em como normalizar seus dados depois de ler isso.

Como preparar os dados de entrada:

A idéia básica é que você deseja que uma variação significativa em cada parâmetro de entrada seja refletida por uma variação significativa na ativação do neurônio em que essas entradas estão sendo alimentadas. Observando um gráfico da derivada da função de ativação tanh (x), você verá que a região de inclinação significativa está a uma distância de um ou dois da origem. Isso significa que, se a entrada para a função de ativação é 2000 ou 3000 (valores de x para os quais a derivada é insignificante pequena), a saída da ativação será quase idêntica ... portanto, o estado do seu neurônio será independente da diferença entre 2000 e 3000, e sua rede nunca produzirá nenhum poder preditivo a partir de valores nesse intervalo.

Portanto, se você deseja inserir a metragem quadrada da casa em um neurônio, você precisa normalizar a metragem quadrada para que a rede possa diferenciar entre 2000 e 3000. Uma maneira de fazer isso para que todas as variações significativas em seu os dados são "notados" pelo neurônio, para z-score-normalizar as entradas .

  • Reúna todos os seus valores de metragem quadrada (do seu conjunto de treinamento) e calcule a média e o desvio padrão. Armazene a média e o desvio padrão - você precisará dessas informações para normalizar novos valores de metragem quadrada ao testar.

  • Normalize o vetor de valores de metragem quadrada subtraindo a média e depois dividindo o resultado pelo desvio padrão (todas as operações, é claro, em elementos). Subtrair a média centraliza seus dados na origem e dividir pelo desvio padrão garante que a maioria esteja entre -1 e 1, onde a saída do neurônio é mais sensível à entrada. Isso é chamado de normalização do escore z porque cada valor de entrada é substituído pelo seu escore z .

  • Faça o acima para cada variável de entrada.

Agora, quando você coloca cada valor de entrada através de um neurônio, a saída do neurônio é uma ativação entre -1 e 1 (veja a imagem de tanh (x)). Como isso já está na faixa 'sensível' da função de ativação, você não precisa se preocupar em alterar a saída dos neurônios da camada de entrada antes de enviá-los para a primeira camada oculta. Apenas dê a qualquer neurônio da camada oculta as saídas da camada anterior diretamente - elas serão capazes de lidar com elas muito bem.

Quando você alcança a última camada (o (s) neurônio (s) de saída), o que você obtém é novamente outra ativação entre -1 e 1. Você precisa converter isso novamente em um valor para a casa em questão , se esse valor será usado como uma previsão em um conjunto de testes ou para calcular o erro durante o treinamento. No entanto, você só precisa ser consistente e usar o mesmo procedimento de desnormalização no treinamento e no teste. Uma maneira de pensar sobre isso é: quando o (s) neurônio (s) de saída retorna 1, isso significa que a rede está retornando o valor máximo possível da casa como sua previsão. Qual deve ser o valor mais alto que a rede pode estimar? A abordagem correta aqui simplesmente depende da sua aplicação. Isto é o que eu fiz:

  • Calcule a média da variável de saída [the / each] e armazene-a.
  • Calcule o desvio máximo da variável de saída da média. Pitão:MaxDev = max([abs(DataPoint-numpy.mean(TrainingData)) for DataPoint in TrainingData])
  • Quando a rede retornar saída (s) entre -1 e 1, multiplique a saída por MaxDeve adicione-a à média.

Você pode fazer duas verificações rápidas básicas para verificar se o seu esquema de normalização-renormalização é adequado (essas são condições necessárias, mas talvez não suficientes):

  1. Se todos os valores de entrada são médios (por exemplo, número médio de quartos, pés quadrados médios, etc.), a saída da rede é igual à média da variável de saída (por exemplo, valor da casa)? (Deveria ser.)
  2. Se todos os valores de entrada forem anormalmente altos / baixos, a saída da rede também é anormalmente alta / baixa? (Isso só funciona se todas as entradas estiverem relacionadas positivamente à saída ... se algumas delas estiverem relacionadas inversamente, você terá que pensar um pouco mais).

Observe que o esquema aqui apresentado satisfaz essas duas condições.

Observe que esse esquema permitiria à sua rede prever apenas valores internos dentro do intervalo de valores internos no seu conjunto de dados de treinamento. Dependendo da aplicação, esse comportamento pode ser desejável ou indesejável.

Por exemplo: convém impossibilitar sua rede de prever valores residenciais negativos. Pense em como você faria isso. Des Normalize a saída para que -1 seja mapeado para 0.

Se você deseja definir um limite para os valores que sua rede pode prever, poderá executar a saída da rede através de uma função que mapeia o intervalo [-1,1] para todos os números reais ... como arctanh (x)! Contanto que você faça isso durante o treinamento, sua rede ajustará seus pesos para acomodar isso.

Eu espero que isto tenha sido útil. Diga-me se tiver mais perguntas. Meu módulo ANN está em Python, a propósito, então eu posso ter conselhos específicos de idioma.

Marko Bakić
fonte
Isso foi muito útil! Todo blog / tutorial que encontro me parece evitar (quase deliberadamente) descrever esse processo, mas sim, isso faz sentido. Vai demorar um pouco para eu digerir corretamente, mas voltarei se tiver alguma dúvida. Muito grato!
David
Então, algumas perguntas. Se meu quadrado. Os dados de treinamento dos pés eram {2000, 800, 850, 550, 2000}; então, minhas entradas do z-score para {1900, 1500, 600} seriam (se eu calculei corretamente) {1,0496, 0,4134, -1,0177}. Então, um desses valores é> 1 e um é <-1, o que eu faria com eles? Introduzi-los nos nós da camada de entrada independentemente ou arredondá-los para 1 e -1? Por que 1900 e 600 produzem esses valores quando estão dentro da faixa 550 - 2000? Isso é apenas um truque dos dados porque existe um conjunto de dados tão pequeno?
David
0 0umandthemumaxEumvocêm
Lembre-se de que as entradas não precisam estar estritamente entre 1 e -1. Tudo o que você precisa para as entradas é que a maioria dos dados esteja nesse intervalo. Um valor maior ou menor que um significa que o ponto está a mais de um desvio padrão da média, portanto, esse ponto está mais próximo da extremidade superior dos dados. Deve ser um pouco raro que seus dados saiam de [-1, 1], ainda mais raro eles saírem de [-2, 2] e extremamente raro sair de [-3, 3]. Olhe para tanh (x) e você verá que o intervalo sensível não é apenas estritamente entre -1 e 1, mas vai um pouco além disso.
Marko Bakić
Em relação à desnormalização de saída, essa desnormalização min-max foi o que fiz na minha implementação e sua interpretação está correta, mas você não precisa necessariamente fazer isso. Você pode fazer com que 1 corresponda ao dobro do valor máximo da casa - para que sua rede possa prever valores da casa acima do que você treinou.
Marko Bakić