Category: Data

  • Redes Neurais 3: Implementação de um Perceptron em Python

    Com os conceitos dos posts anteriores e todo esse embasamento, vamos seguir aos notebooks Jupyter!

    Eu gosto de começar um projeto pensando em como podemos representá-lo em classes. Parece razoável pensar em uma classe Perceptron com alguns métodos que falamos anteriormente.

    Minha estratégia de implementação será:

    1. Discutir minha definição de classe do Perceptron;
    2. Implementar os métodos concretos;
    3. Determinar um data set de exemplo para um teste;
    4. Ver se o perceptron aprende mesmo.

    Definindo a classe Perceptron

    Vamos pensar em quais atributos e métodos vamos precisar para desenhar nossa classe Perceptron.

    Atributos

    • Taxa de aprendizagem (η);
    • Número de Epochs (para mais informações, veja [1]);

    Métodos

    • Método para a função ativação: _activation(X);
      • Descrição: Como função de ativação, escolhi a função degrau, descrita no post anterior. Outras funções são comuns para esta finalidade (para mais informações, veja [2]). 
    • Método para a função soma: _sum(X);
      • Descrição: O processo de sum vai multiplicar X pelo peso correspondente. 
    • Método para iniciar um treinamento: fit(X, y);
      • Descrição: É o método que vai de fato colocar as epochs para rodar, calcular os erros e manter um historico de erros na lista _errors
    • Método para gerar uma predição: predict(X);
      • Descrição: Passa o input X para a função de soma e de ativação e retorna a classe esperada.

    Implementação

    Teste

    Vamos testar nosso perceptron! Para fazer isso, vamos utilizar um método muito pratico do sklearn, o make_blobs. Este método cria dados concentrados em volta de um ponto. É bastante util para gerar dados para testes de regressão e classificação. Nosso perceptron é capaz de aprender a classificar dados lineares.

    Pronto. Vamos colocar nosso perceptron para rodar e classificar os blobs.

    Para isso, basta inicializarmos a nossa classe anterior, separar os X (features) e o y (classe).

    Vamos em seguidar rodar o comando fit do perceptron para treinar os pesos.

    Após alguns segundos de treinamento, nosso perceptron já vai ter aprendido os pesos para classificar os blobs.

    Com a ajuda do método plot_decision_regions da lib mlxtend, podemos plotar a região de classificação:

    Vamos também dar uma olhada no histórico de erros:

    Conforme os pesos foram sendo corrigidos, o perceptron passa a classificar 100% dos pontos de maneira correta.

    Espero que tenha sido interessante para você leitor como foi pra mim construir essa série de posts sobre Machine Learning!

    Até a próxima! 


    Bibliografia

    [1] https://towardsdatascience.com/epoch-vs-iterations-vs-batch-size-4dfb9c7ce9c9

    [2] https://medium.com/the-theory-of-everything/understanding-activation-functions-in-neural-networks-9491262884e0

  • Redes Neurais 2: Perceptrons de Rosenblatt

    “For me there is no absolute knowledge: everything goes only by probability. Both Descartes and Schelling explicitly reported an experience of sudden illumination when they began to see everything in a different light.”
    Wang, H.  (1996)

    Eu acho fundamental (e interessante à beça) alinhar a história com o pensamento, vamos começar então pelo começo.

    História e filosofia por trás do perceptron de Rosenblatt

    Com o advento do computador, as idéias de McCulloch e Pitts puderam ganhar um pouco mais de tangibilidade. Já éramos capazes de construir máquinas para realizar cálculos por nós.

    Frank Rosenblatt, psicólogo estadunidense, sugeriu um método de aprendizado computacional. Seu objetivo era transcrever o “mundo dos fenômenos”, mundo que nós, humanos, estamos familiarizados, para uma “linguagem”, de modo que um computador pudesse receber estes “fenômenos” como entradas. Como ele mesmo explica:

    Since the advent of electronic computers and modern servo systems, an increasing amount of attention has been focused on the feasibility of constructing a device processing such human-like functions as perceptionsrecognitionconcept formation, and the ability to generalize from experience. In particular, interest has centered on the idea of a machine which would be capable of conceptualizing inputs impinging directly from the physical environment of light, sound, temperature, etc. — the “phenomenal world” with which we are all familiar — rather than requiring the intervention of a human agent to digest the code has necessary information.

    Frank Rosenblatt (1957) [1]

    O objetivo do perceptron, segundo Rosenblatt, é ilustrar de maneira geral algumas das propriedades fundamentais de um sistema inteligente sem se apegar as condições, muitas vezes desconhecidas, de um sistema biológico [2, p2-3].

    Os componentes de um perceptron são:

    • Uma arquitetura de rede;
    • Neurônios MCP;
    • Uma Regra de Aprendizado.

    Na época causou uma grande euforia, porém sem as necessárias ferramentas teóricas e sem a devida capacidade computacional (como o algoritmo de back propagation de 1986), o machine learning ficou durante um bom tempo sem ter alguma aplicação prática. Hoje em dia, têm aplicações em quase os todos campos da ciência e impacto direto na nossa vida.

    Matemática

    Atualmente, o perceptron é um conceito que já foi generalizado em termos de machine learning. O perceptron pertence a categoria de aprendizado supervisionado (vou escrever sobre isso mais pra frente). De maneira simplificada isto quer dizer que o modelo, em sua fase inicial, não sabe nada (que seja útil pelo menos, pois começa com um estado aleatório) e se corrige (diminui seu erro) para aprender o que estamos ensinando a ele.

    O perceptron resolve uma categoria específica de problemas, os chamados problemas de classificação binária. Como vamos ver, o perceptron consegue aprender a classificar pontos em um plano e atualizar sua estimativa conforme novas observações são adicionadas.

    Função de ativação

    A função de ativação (leia-se o que faz o neurônio artificial se ativar ou desativar), ou seja, o output y, é definido como sendo:

    \[
    y=g\left(\sum ^{M}_{j=0} I_{j} \ .\ w_{j}\right) =g\left( w^{T} I\right)
    \]

    Onde I são os inputs do perceptron, w os pesos relacionados a cada input e g uma “função degrau”. Essa função degrau determina basicamente qual classe o perceptron “ativou”. Vamos convencionar para simplificar a utilização das classes “-1” e “1”. Portanto nossa função degrau g pode ser definida como sendo:

    \[
    g(z)=\begin{cases} 1 & \text{if } z\geq \theta \ -1 & \text{caso contrário} . \end{cases}
    \]

    Onde θ é o nosso limite, valor limite, ou threshold, como é comum na literatura em inglês.

    Função degrau utilizada como função de ativação [3].

    Essa abordagem está de acordo com a regra “all-or-none” que escrevi no post anterior.

    De maneira simplificada: o output do perceptron é calculado por uma função degrau que leva como parametro a soma dos inputs vezes os pesos de cada input. Se a soma for > que um número qualquer (inicialmente aleatório), o output é “1”. Caso contrário “-1”.

    É fácil notar que pesos (w) e o valor de threshold (θ) são as variáveis que podemos corrigir aqui, certo? É é justamente onde acontece a aprendizagem.

    Aprendizagem

    A ideia de Rosenblatt começa a ficar interessante nesse momento. A diferença é que o algoritmo proposto por ele é capaz de aprender (se ajustar com o intuito de diminuir o erro) os pesos para os sinais de input. Assim, após um determinado número de interações, o perceptron espontaneamente aprende o que estamos ensinando a ele, nesse caso separar os inputs em duas categorias -1 e 1.

    Para aprender, o perceptron segue o seguinte algoritmo:

    1. Defina os pesos w dos inputs I como números aleatórios;
    2. Para cada conjunto de percepções (ou observações):
      1. Calcule o output do perceptron utilizando a função de ativação g;
      2. Atualize os pesos do perceptron para que se aproxime da resposta correta.

    O calculo de atualização dos pesos é a etapa mais bela desse algoritmo. Para cada iteração, vamos atualizar os pesos levando em consideração o peso anterior e o quão errado ele estava, usando, para isto, o valor “alvo” (esperado) e o valor “saida” (encontrado):

    \[
    w_{j} =w_{j} +\Delta w_{j}\\
    \]

    Onde:

    \[
    \Delta w_{j} =\eta \ (\text{alvo}^{(i)} -\text{saida}^{(i)} )\ x^{(i)}_{j}
    \]

    e η é a taxa de aprendizado (learning rate), geralmente um número bastante pequeno, utilizado para que o perceptron não fique procurando a solução ideal muito longe, “alvo” é a label real do objeto e “saída” a label que o perceptron julgou ser verdadeira.

    É interessante notar que caso o perceptron julgue uma label como correta, o delta será zero:

    \[
    \begin{array}{l}
    \Delta w_{j} =\eta (-1^{(i)} – -1^{(i)} )\ x^{(i)}_{j} =0\\
    \Delta w_{j} =\eta (1^{(i)} -1^{(i)} )\ x^{(i)}_{j} =0
    \end{array}
    \]

    Desta maneira, a cada nova interação, os pesos são corrigidos e atualizados de modo que esteja cada vez mais próximo do resultado verdadeiro das observações que entregamos a ele.

    Um abraço!


    Bibliografia

    Referências

    [1] Frank Rosenblatt, The Perceptron – A perceiving and recognizing automaton. January 1957 – https://blogs.umass.edu/brain-wars/files/2016/03/rosenblatt-1957.pdf

    [2] http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.335.3398&rep=rep1&type=pdf

    [3] https://sandipanweb.wordpress.com/2016/07/09/convergence-of-the-gradient-descent-algorithms-stochastic-and-batch-for-the-linear-logistic-regression-and-perceptron/

    [4] http://sebastianraschka.com/Articles/2015_singlelayer_neurons.html

    Leituras

    https://blogs.umass.edu/brain-wars/files/2016/01/rosenblatt-1967.pdf

    https://babel.hathitrust.org/cgi/pt?id=mdp.39015039846566;view=1up;seq=1;size=125

    https://hdl.handle.net/2027/mdp.39015039846566

  • Redes Neurais 1: O primeiro modelo de neurônio artificial de McCulloch e Pitts

    Obter um embasamento teórico mais robusto em machine learning + não ter encontrado blogs com o formato que eu gosto de ler = me veio a motivação para fazer uma série de posts sobre redes neurais com um pouco mais de profundidade!

    Obter um embasamento teórico mais robusto em machine learning + não ter encontrado blogs com o formato que eu gosto de ler = me veio a motivação para fazer uma série de posts sobre redes neurais com um pouco mais de profundidade!

    Biologia & Matemática

    Começando em 1943. Uma fusão de biologia com matemática criou o paper A Logical Calculus of the Ideas Immanent In Nervous Activity [1]. A junção poderosa produziu um modelo abstrato para os neurônios artificiais criado pelos cientistas Warren S. McCulloch e Walter H. Pitts.

    Eles observaram alguns comportamentos dos neurônios biológicos. Entre eles: a observação de fenômenos de refração de sinais caso os neurônios já houvessem sido excitados, um número fixo obrigatório de sinapses para que ele alterasse o seu estado (all-or-none), entre algumas outras características muito interessantes.

    Ao final, foram descritas 5 suposições para que os cálculos dos cientistas pudessem ser coerentes. Então eles descreveram (abaixo uma tradução livre direto do paper) os tópicos:

    A atividade do neurônio é um processo de “all-or-none“.
    Um certo número fixo de sinapses precisam ser “disparadas” dentro de um período de adição latente para excitar o neurônio a qualquer momento. Este número independe de qualquer atividade prévia ou localização do neurônio.
    O único delay significativo dentro de um sistema sináptico é o delay sináptico.
    A atividade de um inibidor em um determinado momento pára completamente a atividade de um determinado neurônio naquele momento.
    A estrutura da rede não se altera com o tempo.(mcculloh; pitts, 1943).

    Abaixo segue uma esquemática do modelo de neurônio artificial:

    Um neurônio completo com entradas, pesos, uma somatória para calcular o número resultante do Input In vezes o peso Wn (In x Wn) e a função de ativação com o número T de limite para que o neurônio possa ativar em um output y.

    A função após a soma, neste caso, aplica-se uma função simples:

    • Pegue a soma dos inputs vezes os pesos (∑Ii  . Wi):
      • Se a soma for > que  o limite T, y = 1;
      • y = 0 caso contrário.

    Ao colocarmos os parâmetros corretos neste modelo de neurônios artificiais podemos construir coisas interessantes, como portas lógicas:

    NOT, AND e OR gate usando neurônios artificiais. [2].

    Em seguida, Rosenblat desenvolveu, incluindo algumas melhorias no modelo proposto por McCulloch e Pitts, o Perceptron.

    Toda essa teoria, que começou muitos anos atrás, possibilita, hoje, juntamente com os avanços tecnológicos no quesito de velocidade computacional e memória extremamente veloz, a construção de soluções para problemas muito complexos, que de certa forma ensinam o computador como agir dado uma entrada. Deixou de ser uma programação guiada a algoritmos rígidos e passou a ser uma programação por exemplos e aprendizagem.

    É uma mistura de prazer e orgulho viver em uma época como a nossa.

    Bom, é isso pessoal. Até o próximo post!

    Links e leituras complementares

    [1] http://www.cse.chalmers.se/~coquand/AUTOMATA/mcp.pdf
    [2] http://www.cs.bham.ac.uk/~jxb/NN/l3.pdf