INTERNOS DE APRENDIZAGEM DE REDE NEURAL (REGRESSÃO LOGÍSTICA)

Serban Liviu Seguir Dez 14, 2017 · 17 min ler

Introdução

Neste post estaremos falando sobre regressão logística ou em termos mais simples, classificação. A classificação é provavelmente a aplicação mais interessante do aprendizado de máquina em geral e das redes neurais em particular. Dado um conjunto de imagens, com dígitos, por exemplo, o trabalho de uma rede neural é produzir o dígito que ele viu. Essa é a classificação e é diferente da regressão linear, também conhecida como previsão. Na regressão linear , o resultado (variável dependente) é contínuo. Pode ter qualquer um de um número infinito de valores possíveis. Na regressão logística , o resultado (variável dependente) tem apenas um número limitado de valores possíveis. A regressão logística é usada quando a variável de resposta é de natureza categórica. Bem, isso soa como um bocado. No caso de regressão linear ou predição, você recebe um conjunto de variáveis aleatórias independentes que normalmente notamos como X1, X2 etc, e o resultado é outra variável aleatória que chamamos de Y e essa variável aleatória pode assumir qualquer valor. Como exemplo, considere que queremos prever os preços da casa com alguns dados de entrada, como localização, tamanho, número ou quartos, etc. Nossos dados de treinamento serão um vetor de pares [(X1, Y1), (X2, Y2), … (Xn, Yn)] onde cada X (a entrada) é um vetor de diferentes parâmetros como o mencionado acima, e Y poderia ser um valor de ponto flutuante. Após o treinamento, gostaríamos de usar este modelo para prever o preço de casas que não vimos (não estavam em nosso conjunto de treinamento).

Trending AI Articles:

1. Tutorial da TensorFlow Object Detection API

2. Keras Cheat Sheet: Redes Neurais em Python

3. Google vai bater a Apple em seu próprio jogo com IA superior

4. TensorFlow Object Detection API: noções básicas de detecção (2/2)

Assim, foi dada uma casa com as seguintes características (parâmetros): 7 quartos, 2 varandas, 3 casas de banho, 4 estacionamentos, construídos em 1998 a partir de concreto, situados em uma área residencial do norte, com vista para o lago, dadas as coordenadas GPS xey , com uma área total de 450 metros quadrados, um quintal de 300 metros quadrados, a 500 metros da primeira estação de metrô ea 300 metros do jardim de infância mais próximo etc. Nosso modelo produzirá um preço em euros deste exemplo de 300.000. Obviamente, o número de detalhes pode aumentar polinomialmente. Aqui estão apenas alguns detalhes simples, como número de quartos, localização etc. Mas uma previsão muito séria pode levar em conta coisas como o tipo de materiais de construção e outras utilidades. Portanto, esse não é um problema simples que poderia ser resolvido por algoritmos com ifs e elses !

Além disso, se alterarmos apenas um dos parâmetros de entrada, digamos o número de quartos ou um tipo de material de construção usado, nosso modelo produzirá outro preço, diferente do primeiro. Assim, nossa produção pode levar todo tipo de valores de 100 euros a milhões de euros de dólares. Dizemos que o valor de saída é contínuo.

Na classificação, por outro lado, a variável de saída (a dependente) não é contínua, mas discreta. Isso significa que Y obterá valores de um conjunto fixo de valores. Na detecção de rosto, por exemplo, o valor de Y será ou temos uma face na imagem ou não. Isso significa que Y será 1 ou 0. Na tarefa OCR, para reconhecimento de dígitos, a entrada é uma pequena imagem jpeg de um dígito, como 5, e a saída será, nesse caso, o número 5. Portanto, uma rede neural treinado para reconhecer todos os 10 dígitos, produzirá qualquer um dos 10 valores de 0 a 9 e nada mais. Uma rede neural como essa não produzirá valores flutuantes como 1.7854, por exemplo. Não faria qualquer sentido. Então, dizemos que a saída, neste caso, é categórica

Algumas palavras sobre regressão linear

Portanto, agora que sabemos a diferença entre classificação e previsão, é hora de entender como treinar uma rede neural simples que pode classificar alguns números em uma das duas categorias. Chamaremos essa rede neural de classificador, ou, para ser mais preciso, um classificador binário. Antes de prosseguirmos, espero que você leia meu primeiro post sobre regressão linear , ou você está familiarizado com o que é regressão linear, e o treinamento de redes neurais funciona em geral (você sabe coisas como derivadas parciais, descida de gradiente, função de custo, coisas assim).

De qualquer forma, vamos recapitular alguns desses materiais aqui apenas para ter um lugar para começar. Assim, no caso do tipo mais simples de regressão linear, como o apresentado no meu post anterior, recebemos um conjunto de pontos, x no eixo OX e seus correspondentes ys no eixo OY. É assim que nosso simples conjunto de treinamento será:

Ou podemos visualizá-los como pontos no plano. Aqui está um exemplo disso:

Também recebemos a rede neural mais simples de todas, que é composta de um neurônio, com uma entrada, ponderada por um peso m , e um viés que chamamos de b . Nossa tarefa é encontrar um valor para o peso m (ou w ) e para o viés b tal que, quando usamos um dos x no conjunto de treinamento como entrada para o neurônio, a saída do neurônio deve ser tão próxima quanto possível, o correspondente y para esse x . Em outras palavras, os parâmetros do nosso neurônio, o valor do peso m e o viés b , poderiam ser interpretados como os parâmetros de uma equação de linha, e a tarefa de treinar o neurônio significa que precisamos encontrar valores adequados para ambos m ( o declive da linha) eb (o intercepto) tal que a linha, ajusta o conjunto de dados. Primeiro começamos com valores aleatórios para m e b , como na imagem abaixo:

e depois do treino, devemos acabar com algo assim:

Na última imagem, você pode ver que a diferença ou erro, entre o que o nosso modelo produz e o que deve produzir (o valor desejado do conjunto de treinamento) é mínimo em média (para cada ponto, não apenas para um deles) . O erro entre a saída e os valores desejados são todas as linhas vermelhas na imagem abaixo:

Neste exemplo, m é a inclinação da linha eb é a interceptação. Então o neurônio modela uma equação de linha. Em 3 dimensões será um plano e em dimensões superiores será um hiperplano

Leia mais na postagem do blog anterior

Alguma terminologia

Antes de prosseguirmos, acho importante ter certa terminologia. Um neurônio a tem um conjunto de entradas e cada entrada é multiplicada por um valor de peso. Depois disso, adicionamos um valor de polarização (não obrigatório) e toda essa soma a chamamos de soma ponderada e geralmente nos referimos a ela com a letra z. Essa soma ponderada é então usada como entrada para uma função de ativação, como sigmóide ou tanh, que esmaga essa soma ponderada em um intervalo como (0, 1) ou (-1, 1).

A soma ponderada ficará assim:

Depois disso, essa soma ponderada se tornará a entrada para uma função de esmagamento também conhecida como função de ativação do neurônio e a saída será referenciada pela letra a.

Na próxima seção, veremos o tipo mais clássico de função de ativação, o sigmóide

Conheça o sigmóide

O sigmóide é uma função limitada crescente monotonicamente contínua. As funções mapeiam cada número real no intervalo aberto (0, 1)

Este é o gráfico de funções:

E é assim que é definido:

Se você fitar o suficiente nessa definição, você entenderia que, basicamente, se x for muito grande, o resultado será muito próximo de 1 (mas nunca 1) e se for muito negativo, o resultado será muito próximo de 0 (mas nunca 0). No gráfico eu também mostro as duas assíntotas (y = 1 e y = 0). quando x = 0, o resultado é 0,5, isto é, no meio do intervalo aberto (0, 1).

Agora, a questão é como podemos usar todo esse conhecimento para classificar os dados como pertencentes a uma das duas categorias, 0 ou 1. Dado um conjunto de treinamento da mesma forma como acima, com a diferença de que o componente y agora seja 0 ou 1 como T = [(1, 0), (2, 0), (3, 1), (4, 1)]. Temos também como modelo o único neurônio com uma entrada ponderada e um viés como no exemplo de regressão linear. Também começaremos com valores aleatórios para o peso m e o viés b. Mas, após o treinamento, quando usamos como entrada o valor 2, por exemplo, gostaríamos de obter a classe dessa entrada, que nesse caso será 0 e quando usaremos 4 como entrada, gostaríamos de obter como saída o valor 1. Mas como podemos modelar isso? Isso não é diferente da regressão linear. Se você pensar sobre isso, na regressão linear após o treinamento, você quer que seu modelo, para uma entrada x, produza um valor o mais próximo possível do valor y real do conjunto de treinamento. Você deseja que a diferença de erro seja a mais baixa possível para cada ponto de dados de treinamento. A única diferença aqui é que temos apenas dois valores desejados (0 e 1) para qualquer ponto de dados de treinamento. Então, para ter certeza de que nosso modelo / neurônio produz um valor tão próximo quanto possível do valor real desejado, devemos usar uma função de esmagamento como o sigmóide. Assim, se ligarmos uma função sigmoide ao nosso neurônio, após o treinamento, para um ponto de dados com o rótulo 0, gostaríamos que a soma ponderada z fosse negativa, porque um valor negativo usado como entrada para a função sigmoide produziria um valor próximo a zero. Quanto mais negativo, a soma ponderada, mais próximo de zero será a saída sigmoide. E se usarmos como entrada um ponto de dados com o rótulo 1, gostaríamos que nesse caso a soma ponderada z fosse positiva, porque então a saída do sigmóide seria próxima de 1. Faz sentido?

Na regressão linear, encontramos uma linha / plano / hiperplano que se ajusta aos dados de treinamento. Na regressão logística, encontramos uma linha / plano / hiperplano que pode separar os dados de treinamento por categorias

Regressão Logística

Vamos começar com um exemplo simples. Vamos supor que temos esses dados de treinamento e um neurônio inicializado com alguns valores aleatórios para o peso meo viés b:

Neste caso, o peso m = 1 e o viés b = 1 . Mas lembre-se que, ao contrário da regressão linear, também adicionamos a função sigmoide ao neurônio.

Então, se pegarmos o valor 2 deste gráfico e calcularmos o que é normalmente conhecido como a soma ponderada do neurônio, obteremos o seguinte: z = 2 + 1 => z = 3 e agora usaremos 3 como entrada para a função sigmóide vamos conseguir isso:

sigmloid (3) = 0,952574126822

Como o rótulo de 2 é 0, esperávamos que o neurônio sigmoide emitisse algum valor abaixo de 0,5, como 0,00001 ou algo assim. A saída real é muito próxima de 1, então podemos dizer que, para esses dados de entrada, o neurônio a classificou erroneamente. Os únicos valores para os quais o neurônio dará um bom valor são 3 e 4 no exemplo acima. Por um bom motivo. Para 3, o valor da soma ponderada é 4 e, em seguida, sigmóide (4) = 0,982013790038 . Muito muito perto do rótulo real de 1 para esse ponto de dados. Mesma história para 4 também.

Agora, como podemos interpretar esses valores sigmoides como probabilidades? A resposta é usar o logaritmo natural da saída do neurônio.

Vamos supor que tomamos o valor 4. Usando o único neurônio na imagem acima (onde m = 1 e b é 1), teremos uma soma ponderada de 5. Agora

sigmóide (5) = 0,993307149075 . Isso é muito bom porque esse valor é muito próximo do rótulo real para este exemplo de treinamento, que é 1. Se, então, calcularmos o logaritmo natural desse valor, obteremos isso:

ln (0,993307149075) = -0,00671534848984 .

Agora, se olharmos no gráfico da função de log natural:

Podemos ver que, para um valor muito próximo de 1, o resultado no eixo OY está muito próximo de 0, mas é um valor negativo. Se usarmos em vez de -ln (x) como uma função ao invés do simpe ln (x) , teremos o seguinte gráfico:

ln (x) é a dupla função de ln (x). É basicamente a mesma função invertida de cabeça para baixo. Aqui, um valor próximo de 1 no eixo OX terá um valor correspondente no eixo OY próximo de 0, mas positivo desta vez.

Agora vamos dar um exemplo de um ponto de dados que é erroneamente classificado pelo nosso neurônio. Tomemos por exemplo 2 como uma entrada para o neurônio. Com base na equação de linha acima, a saída do neurônio antes do sigmóide será 2 + 1 = 3. Sabemos agora que sigmloid (3) = 0.952574126822 . Também é muito próximo de 1, embora o rótulo para este exemplo seja 0. Se pegarmos o logaritmo natural para esse valor, obteremos um valor muito próximo de 0, assim como no caso anterior. Isso não vai ajudar muito. O truque é tentar pegar o logaritmo natural de 1 – sigmóide (4). Então, nosso cálculo de log se tornará:

ln (1-0,982013790037) = ln (0,017986209963) = -4,01814992787 .

O -ln (0.017986209963) será 4.01814992787 . Isso é um valor bastante grande. Nosso objetivo na regressão logística, assim como na regressão linear, é minimizar uma função de custo. Se a função de custo para um determinado ponto de dados de treinamento for menor, melhor. Neste caso, queremos minimizar essa função de logaritmo natural. Em outras palavras, queremos que os valores sejam próximos de zero quanto possível para as duas classes (1 e 0). No primeiro caso em que o ponto de dados de treinamento era 3, tínhamos -ln (0,993307149075) = 0,00671534848984, que estava muito próximo de 0. Assim, para este caso, o erro é muito pequeno, o que significa que estamos fazendo um bom trabalho. No segundo exemplo, para o ponto de dados de treinamento 2,

Em (0,017986209963) será 4.01814992787 que é um valor grande, o que significa que estamos fazendo um trabalho ruim. Portanto, esse log natural retornará um grande custo se os dados forem classificados incorretamente e um custo muito pequeno se os dados forem classificados corretamente. Nosso objetivo é minimizar essa função como um todo. Abaixo está a função que usamos e é chamada entropia cruzada:

O y representa o rótulo da classe (0 ou 1) e a é a saída do neurônio

Portanto, se o rótulo da classe for 1, por exemplo, obviamente, o segundo termo se tornará 0 e calcularemos apenas o primeiro termo ln (a). Por outro lado, se o rótulo de classe for 0, o primeiro termo se tornará 0 e nós calcularemos o segundo termo ln (1 – a). Como cada termo dessa soma é negativo, o menos no início tornará a função positiva.

Bem, vamos tentar o método de gradiente descendente neste exemplo simples para ver como a linha muda sua inclinação e interceptação. Mais uma vez, aqui estão os nossos dados de treinamento:

T = [(1, 0), (2, 0), (3, 1), (4, 1)]

e esta é a configuração inicial:

Então o m = 1 e b = 1. Agora pegamos o primeiro ponto de dados 1 com o rótulo 0. Esse é o primeiro ponto no eixo OX

Assim, o neurônio calculará isso: z = 1 * 1 + 1 = 2 => sigmóide (2) = 0,880797077975

E agora vamos calcular a entropia cruzada para este exemplo em particular: C (w, b) = – [0ln (0,880797077975) + ln (1-0,880797077975)] =

ln (0,119202922025) = – (- 2,12692801102) = 2,12692801102

Portanto, o custo do erro para este exemplo é grande. Precisamos empurrar um pouco a inclinação e o viés para minimizar a função de custo.

Precisamos calcular as derivadas parciais da função custo em relação a ambos, m e b.

Primeiro, vamos calcular a derivada parcial da entropia cruzada em relação a m (o peso da entrada para o neurônio ou o declive da linha, como chamamos neste post)

Como você pode ver, isso parece muito assustador. mas não há necessidade de ter medo. Tenha em mente que a derivada do ln (x) = 1 / xe que, em vez de x, temos a saída do neurônio que é a função sigmóide. Também tenha em mente que a derivada da função sigmóide é:

Além disso, você precisa saber qual é a regra da cadeia. Caso você tenha problemas com isso, verifique alguns dos recursos aqui na academia Khan:

https://www.youtube.com/watch?v=rAof9Ld5sOg

Com um pouco de álgebra, fizemos com que a derivada parcial da entropia cruzada em relação ao peso m do neurônio fosse basicamente a diferença de erro (neuron_output (z) -y) * x onde neuron_output é a função sigmóide . A derivada parcial da função de custo para o viés é basicamente a mesma sem o x no final.

PS: tenha em mente que a função de entropia cruzada tem um sinal de menos no início, então se multiplicarmos por outro menos, obteremos o seguinte resultado final da derivação:

Então, agora voltando ao nosso exemplo, a saída da função de custo para o ponto de dados 1 foi 2.12692801102. Agora vamos supor que estamos usando uma taxa de aprendizado de 0,5. Atualizando o peso m de acordo com a equação de gradiente de descida:

o peso m será:

m (t + 1) = m (t) -0,5 * (0,880797077–0) * 1 => m = 1-0,5 * 0,880797077 => m = 1–0,4403985385 => m = 0,5596014615

Fazendo o mesmo para o viés: b (t + 1) = b (t) -0,5 * (0,880797077–0) =>

b = 1–0,4403985385 => b = 0,5596014615

Agora que os parâmetros, ambos m e b foram atualizados com seus derivados, é assim que a linha ficará:

Repetindo este processo para o próximo ponto de dados no conjunto de treinamento, nos dará o seguinte:

para o ponto de dados 2 com o rótulo 0, teremos:

z = 0,5596014615 * 2 + 0,5596014615 = 1,6788043845

sigmóide (1,6788043845) = 0,842746146999 => C (mb) = – [0ln (0,84274614699980) + ln (1-0,84274614699] => C (m, b) = – [ln (0,842746146999)] => C (m, b) = – [- 0,1710894968167155] = 0,1710894968167155

m (t + 1) = m (t) -0,5 * (0,842746146999-0) * 2 = 0,5596014615- 0,842746146999 = -0,283144685499

b (t + 1) = b (t) -0,5 * (0,842746146999–0) = 0,5596014615–0,4213730734995 = 0,1382283880005

E agora vamos fazer de novo para o terceiro ponto de dados no conjunto de treinamento (3,1)

z = -0,283144685499 * 3 + 0,1382283880005 => z = -0,7112056684965 => sigmóide (-0,7112056684965) = 0,3293324862808

m (t + 1) = m (t) -0,5 * 3 * (0,3293324862808–1) => m = -0,283144685499 – (- 1,0060012705788) => m = -0,283144685499 + 1,0060012705788 => m = 0,7228565850798

b (t + 1) = b (t) -0,5 * (0,3293324862808–1) =>

b = 0,1382283880005- (-0,3353337568596) => b = 0,4735621448601

Mas passar por esses exemplos e calcular a atualização de peso e bias manualmente em cada etapa do gradiente é muito trabalhoso. A melhor maneira que podemos fazer é executar um script python muito simples que faça isso para nós. Abaixo está o script python que irá treinar esta rede neural muito simples com um neurônio. Começamos com peso 1 e viés 1 e treinamos por 50 épocas (uma época é quando você passou por todos os exemplos de treinamento uma vez). O feed forward é simples assim. Nós multiplicamos a entrada com o peso e adicionamos o viés e então usamos isso como entrada para a função sigmóide. A parte interessante vem depois, quando temos que calcular as derivadas tanto para o peso w quanto para o viés b em relação à função de entropia cruzada. As fórmulas para isso são dadas acima nós fizemos isso matematicamente.

 import numpy como np 

treinamento = [(1,0), (2,0), (3,1), (4,1)]

def sigmoid (x):
return 1 / (1 + np.exp (-x))

def feedforward (peso, polarização, entrada):
retorno sigmoide (peso * entrada + viés)

trem de def (w, b):
l = 0,5 #a taxa de aprendizado
para par no treinamento: # para cada exemplo no conjunto de treinamento

# primeiro dfo o feedforward que retornará a qual é o resultado sigmóide
a = feedforward (w, b, par [0])
#now recompute o peso e o viés atualizando-os com sua função derivada de custo de entropia cruzada
#que nós derivamos acima
w = w - l * (a - par [1]) * par [0] #next_w = anterior_w - learning_rate * (feedforward_res_of network - training_label) * entrada
b = b - l * (a - par [1]) #next_b = previous_b - learning_rate * (feedforward_res_of network - training_label)
retorno w, b

#starting weights
m = 1
b = 1

#train por 30 épocas
para i no intervalo (1, 50):
m, b = treinar (m, b)
impressão w, b

Após a primeira época, m = 0,559601461011 eb = 0,559601461011

Plotando isso nos dará isto:

Não é muito encorajador. esperando por algumas épocas. Após 10 épocas teremos m = 1,58751423484 e b = -2,07629893405 . Plotar isso nos dará isto:

Isso é um pouco melhor ainda. Vamos continuar. Após a 25ª época, obteremos m = 2,28329850052 e b = -4,39147547891 . Agora parece que:

Após as 49 épocas teremos o seguinte m = 2.92254614879 e

b = -6,38781463728 . Plotar isso nos mostrará isso:

Hmm. Agora isso parece interessante. Quando inserimos 1 ou 2 no neurônio (um dos dois pontos de dados com o rótulo 0), obtemos um número negativo e esse número negativo como entrada para o sigmóide resultará em um valor próximo de 0 (o rótulo desses dois pontos de dados). Por outro lado, se inserirmos 3 ou 4 (um dos dois pontos de dados com o rótulo 1), obteremos um número positivo que usado como entrada para o sigmoide final nos dará um número próximo de 1, o real etiqueta desses pontos de dados. Observe também a partir do gráfico, que agora a linha se parece mais com um separador entre as duas classes. Podemos continuar a treinar para mais épocas, o resultado final não será tão diferente do que temos agora. Por exemplo, treinando para um milhão de épocas em vez de 50:

 para i no intervalo (1, 1000000): 
w, b = trem (w, b)
imprimir i, w, b

nós iremos obter os seguintes valores para m e b:

m = 20.9271365027 b = -52.1436231067 O gráfico neste caso será assim:

Isso claramente parece melhor que o que temos na imagem anterior, mas não com muito.A separação é alcançada em ambos os casos, embora nesta imagem a separação é mais pronunciada.

Continua…

Não se esqueça de nos dar o seu ?!