Skip to content

Deep Learning Book

  • Início
  • Capítulos
  • Cursos Online
  • Contato

Deep Learning Book

Em Português, Online e Gratuito

Deep Learning Book

Capítulo 33 – Por que as Redes Neurais Profundas São Difíceis de Treinar?

by

Iniciamos agora a terceira e última parte deste livro, em que estudaremos como funciona Deep Learning e os principais modelos e arquiteturas de redes neurais profundas, com diversos exemplos e aplicações. Mas primeiro temos que responder a seguinte pergunta: Por que as Redes Neurais Profundas São Difíceis de Treinar?

Imagine que você é um engenheiro que foi solicitado a projetar um computador do zero. Um dia, você está trabalhando em seu escritório, projetando circuitos lógicos, estabelecendo portas AND e OU, e assim por diante, quando seu chefe chega com más notícias. O cliente acaba de adicionar um requisito de design surpreendente: o circuito para o computador inteiro deve ter apenas duas camadas de profundidade:

 

shallow_circuit

 

Você fica estupefato e diz ao seu chefe: “O cliente está louco!”

Seu chefe responde: “Eu acho que eles são loucos também. Mas precisamos atender este requisito.”

Na verdade, há um sentido limitado em que o cliente não é louco. Suponha que você tenha permissão para usar uma porta lógica especial que permite a você aplicar o AND (o “e” da lógica) e juntar quantas entradas desejar. E você também tem permissão para uma porta NAND com muitas entradas, ou seja, uma porta que pode aplicar o AND a várias entradas e depois nega a saída. Com essas portas especiais, é possível calcular qualquer função usando um circuito com apenas duas camadas de profundidade.

Mas só porque algo é possível, não é uma boa ideia. Na prática, quando resolvemos problemas de projeto de circuitos (ou quase todos os tipos de problemas algorítmicos), geralmente começamos descobrindo como resolver sub-problemas, e então gradualmente integramos as soluções. Em outras palavras, criamos uma solução através de várias camadas de abstração.

Por exemplo, suponha que estamos projetando um circuito lógico para multiplicar dois números. Provavelmente, queremos construí-lo a partir de sub-circuitos, fazendo operações como adicionar dois números. Os sub-circuitos para adicionar dois números serão, por sua vez, construídos a partir de sub-sub-circuitos para adicionar dois bits. Muito grosso modo, nosso circuito será parecido com:

 

circuit_multiplication

 

Ou seja, nosso circuito final contém pelo menos três camadas de elementos de circuito. Na verdade, provavelmente conterá mais de três camadas, pois dividimos as sub-tarefas em unidades menores do que as descritas anteriormente. Mas você compreendeu a ideia geral.

Então circuitos profundos facilitam o processo de design. Mas eles não são apenas úteis para o design. Existem, de fato, provas matemáticas mostrando que, para algumas funções, circuitos muito superficiais requerem exponencialmente mais elementos de circuitos para serem computados do que circuitos profundos. Por exemplo, uma famosa série de artigos no início dos anos 1980 mostrou que calcular a paridade de um conjunto de bits requer muitos portões exponencialmente, se feito com um circuito superficial.

Por outro lado, se você usa circuitos mais profundos, é fácil calcular a paridade usando um pequeno circuito: basta calcular a paridade de pares de bits, depois usar esses resultados para calcular a paridade de pares de pares de bits e assim por diante. construindo rapidamente a paridade geral. Os circuitos profundos, portanto, podem ser intrinsecamente muito mais poderosos que os circuitos superficiais.

Até agora, este livro abordou redes neurais como o cliente louco. Quase todas as redes com as quais trabalhamos têm apenas uma camada oculta de neurônios (mais as camadas de entrada e saída):

 

rede neural profunda

 

Essas redes simples têm sido extraordinariamente úteis: nos capítulos anteriores, usamos redes como essa para classificar dígitos manuscritos com precisão superior a 98%! No entanto, intuitivamente, esperamos que as redes com muito mais camadas ocultas sejam mais poderosas:

 

rede neural profunda

 

Tais redes poderiam usar as camadas intermediárias para construir múltiplas camadas de abstração, assim como fazemos em circuitos booleanos. Por exemplo, se estamos fazendo reconhecimento de padrões visuais, então os neurônios da primeira camada podem aprender a reconhecer bordas, os neurônios da segunda camada podem aprender a reconhecer formas mais complexas, digamos, triângulo ou retângulos, construídos a partir de bordas. A terceira camada reconheceria formas ainda mais complexas. E assim por diante. Essas múltiplas camadas de abstração parecem propiciar às redes profundas uma vantagem convincente em aprender a resolver problemas complexos de reconhecimento de padrões. Além disso, assim como no caso dos circuitos, existem resultados teóricos sugerindo que as redes profundas são intrinsecamente mais poderosas do que as redes superficiais.

Como podemos treinar essas redes profundas? Nos próximos capítulos, tentaremos treinar redes profundas usando nosso algoritmo de aprendizado: descendente de gradiente estocástico por retropropagação (que já estudamos em detalhes nos capítulos anteriores, mas que agora aplicaremos em redes neurais profundas). Mas vamos nos deparar com problemas, com nossas redes profundas não realizando muito (se for o caso) melhor do que redes rasas.

Essa falha parece surpreendente à luz da discussão acima. Em vez de desistir de redes profundas, vamos nos aprofundar e tentar entender o que está dificultando o treinamento de nossas redes profundas. Quando olharmos de perto, descobriremos que as diferentes camadas da nossa rede profunda estão aprendendo em velocidades muito diferentes.

Em particular, quando as camadas posteriores da rede estão aprendendo bem, as camadas iniciais geralmente ficam presas durante o treinamento, aprendendo quase nada. Este empecilho não é simplesmente devido à má sorte. Em vez disso, descobriremos que existem razões fundamentais para a lentidão do aprendizado, conectadas ao nosso uso de técnicas de aprendizado baseadas em gradientes.

À medida que nos aprofundamos no problema, aprenderemos que o fenômeno oposto também pode ocorrer: as primeiras camadas podem estar aprendendo bem, mas as camadas posteriores podem ficar presas. Na verdade, descobriremos que existe uma instabilidade intrínseca associada ao aprendizado por gradiente descendente em redes neurais profundas de muitas camadas. Essa instabilidade tende a resultar em camadas anteriores ou posteriores ficando presas durante o treinamento.

Mas, ao nos debruçarmos sobre essas dificuldades, podemos começar a entender o que é necessário para treinar redes profundas de maneira eficaz. E isso é exatamente o que faremos nos próximos capítulos.

Agora é que começa a diversão. Até lá.

Referências:

Data Science Para Análise Multivariada de Dados

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 31 – As Redes Neurais Artificiais Podem Computar Qualquer Função?

by

Um dos fatos mais impressionantes sobre redes neurais é que elas podem computar qualquer função. Isto é, suponha que alguém lhe dê alguma função complicada, f(x):

 

image1

 

Não importa qual seja a função, é garantido que existe uma rede neural de modo que, para cada entrada possível, x, o valor f(x) (ou alguma aproximação) seja transmitido da rede, por exemplo:

 

image2

 

Este resultado é válido mesmo se a função tiver muitas entradas, f = f(x1,…, xm) e muitas saídas. Por exemplo, aqui está uma rede computando uma função com m = 3 entradas e n = 2 saídas:

image3

 

Este resultado nos diz que as redes neurais têm um tipo de universalidade. Não importa qual função queremos computar, sabemos que existe uma rede neural que pode fazer o trabalho.

Além do mais, esse teorema da universalidade é válido mesmo se restringirmos nossas redes a ter apenas uma única camada intermediária entre os neurônios de entrada e de saída – uma chamada camada oculta única. Portanto, mesmo arquiteturas de rede muito simples podem ser extremamente poderosas e isso ajuda a explicar porque as redes neurais vem sendo usadas em aplicações avançadas de Inteligência Artificial.

O teorema da universalidade é bem conhecido por pessoas que usam redes neurais. Mas porque é verdade não é tão amplamente compreendido. A maioria das explicações disponíveis é bastante técnica. Por exemplo, um dos artigos originais que comprovou o resultado utilizou o teorema de Hahn-Banach, o teorema da representação de Riesz e alguma análise de Fourier. Se você é um matemático, o argumento não é difícil de seguir, mas não é tão fácil para a maioria das pessoas. É uma pena, já que as razões subjacentes à universalidade são simples e belas.

Nos próximos capítulos, faremos uma explicação simples e principalmente visual do teorema da universalidade. Nós vamos passo a passo através das idéias principais. Você entenderá porque é verdade que as redes neurais podem computar qualquer função. Você entenderá algumas das limitações do resultado. E você entenderá como o resultado se relaciona com redes neurais profundas (Deep Learning).

Os capítulos serão estruturados para ser agradáveis e objetivos. Desde que você tenha apenas um pouco de familiaridade básica com redes neurais, você deve ser capaz de seguir a explicação. No entanto, iremos fornecer links ocasionais para materiais anteriores, para ajudar a preencher quaisquer lacunas em seu conhecimento.

Os teoremas da universalidade são um lugar comum na ciência da computação, tanto que às vezes nos esquecemos do quão surpreendentes eles são. Mas vale a pena lembrar-nos: a capacidade de calcular uma função arbitrária é verdadeiramente notável. Quase qualquer processo que você possa imaginar pode ser considerado como computação de função. Considere o problema de nomear uma peça musical com base em uma pequena amostra da peça. Isso pode ser pensado como computação de uma função. Ou considere o problema de traduzir um texto chinês para o inglês. Mais uma vez, isso pode ser pensado como computação de uma função. Ou considere o problema de analisar um arquivo de filme mp4 e gerar uma descrição do enredo do filme e uma discussão sobre a qualidade da atuação dos atores. Novamente, isso pode ser pensado como um tipo de computação de função. Universalidade significa que, em princípio, as redes neurais podem fazer tudo isso e muito mais.

É claro, só porque sabemos que existe uma rede neural que pode (por exemplo) traduzir o texto chinês para o inglês, isso não significa que temos boas técnicas para construir ou mesmo reconhecer tal rede. Essa limitação se aplica também aos teoremas da universalidade tradicionais para modelos como circuitos booleanos. Mas, como vimos anteriormente no livro, as redes neurais possuem algoritmos poderosos para funções de aprendizado. Essa combinação de algoritmos de aprendizado + universalidade é uma mistura atraente. Até agora, o livro se concentrou nos algoritmos de aprendizado. Nos próximos capítulos, nos concentramos na universalidade e no que ela significa.

A compreensão desse conceito é a chave para as arquiteturas mais avançadas de Deep Learning, que estão por vir mais a frente, neste livro!

Referências:

Desenvolvimento e Deploy de Modelos de Machine Learning

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 25 – Inicialização de Pesos em Redes Neurais Artificiais

by

Quando criamos nossas redes neurais, temos que fazer escolhas para os valores iniciais de pesos e vieses (bias). Até agora, nós os escolhemos de acordo com uma prescrição que discutimos nos capítulos anteriores.

Só para lembrar, a prescrição era escolher tanto os pesos quanto os vieses usando variáveis aleatórias Gaussianas independentes, normalizadas para ter a média 0 e desvio padrão 1 (esse é um conceito fundamental em Estatística e caso queira adquirir conhecimento em Estatística na prática através de projetos, acesse aqui: Matemática e Estatística Aplicada Para Data Science, Machine Learning e IA. 

Embora esta abordagem tenha funcionado bem, foi bastante ad-hoc, e vale a pena revisitar para ver se podemos encontrar uma maneira melhor de definir nossos pesos e vieses iniciais, e talvez ajudar nossas redes neurais a aprender mais rápido. É o que iremos estudar neste capítulo.

Para começar, vamos compreender porque podemos fazer um pouco melhor do que inicializar pesos e vieses com valores Gaussianos normalizados. Para ver porque, suponha que estamos trabalhando com uma rede com um grande número – digamos 1.000 – de neurônios de entrada. E vamos supor que usamos valores Gaussianos normalizados para inicializar os pesos conectados à primeira camada oculta. Por enquanto, vou me concentrar especificamente nos pesos que conectam os neurônios de entrada ao primeiro neurônio na camada oculta e ignorar o restante da rede:

 

rede

 

Vamos supor, por simplicidade, que estamos tentando treinar usando uma entrada de treinamento x na qual metade dos neurônios de entrada estão ativados, isto é, configurados para 1, e metade dos neurônios de entrada estão desligados, ou seja, ajustados para 0. O argumento a seguir aplica-se de forma mais geral, mas você obterá a essência deste caso especial. Vamos considerar a soma ponderada z = ∑jwjxj + b de entradas para nosso neurônio oculto. Ocorre que 500 termos nesta soma desaparecem, porque a entrada correspondente xj é zero e, assim, z é uma soma sobre um total de 501 variáveis aleatórias Gaussianas normalizadas, representando os 500 termos de peso e o termo extra de viés (bias). Logo, z é ele próprio uma distribuição Gaussiana com média zero e desvio padrão ≈ 22.4 (raiz quadrada de 501). Ou seja, z tem uma distribuição Gaussiana muito ampla, sem um pico agudo, conforme a figura abaixo:

 

rede2

 

Em particular, podemos ver neste gráfico que é bem provável que | z | será bastante grande, isto é, z > 1 ou z < -1. Se for esse o caso, a saída σ(z) do neurônio oculto estará muito próxima de 1 ou 0. Isso significa que nosso neurônio oculto terá saturado. E quando isso acontece, como sabemos, fazer pequenas mudanças nos pesos fará apenas mudanças absolutamente minúsculas na ativação de nosso neurônio oculto. Essa mudança minúscula na ativação do neurônio oculto, por sua vez, dificilmente afetará o resto dos neurônios na rede, e veremos uma mudança minúscula correspondente na função de custo.

Como resultado, esses pesos só aprenderão muito lentamente quando usarmos o algoritmo de descida do gradiente. É semelhante ao problema que discutimos anteriormente em outros capítulos, no qual os neurônios de saída que saturaram o valor errado fizeram com que o aprendizado diminuísse. Abordamos esse problema anterior com uma escolha inteligente de função de custo. Infelizmente, enquanto isso ajudou com os neurônios de saída saturados, ele não faz nada pelo problema dos neurônios ocultos saturados.

Temos falado sobre a entrada de pesos para a primeira camada oculta. Naturalmente, argumentos semelhantes aplicam-se também a camadas ocultas posteriores: se os pesos em camadas ocultas posteriores forem inicializados usando Gaussianos normalizados, então as ativações estarão frequentemente muito próximas de 0 ou 1, e o aprendizado prosseguirá muito lentamente.

Existe alguma maneira de escolhermos melhores inicializações para os pesos e vieses, para que não tenhamos esse tipo de saturação e, assim, evitar uma desaceleração na aprendizagem? Suponha que tenhamos um neurônio com pesos de entrada nin. Então, inicializaremos esses pesos como variáveis ​​aleatórias gaussianas com média 0 e desvio padrão:

 

form

 

Isto é, vamos “esmagar os gaussianos”, tornando menos provável que nosso neurônio seja saturado. Continuaremos a escolher o viés como um Gaussiano com média 0 e desvio padrão 1, por motivos pelos quais voltaremos daqui a pouco. Com essas escolhas, a soma ponderada z = ∑jwjxj + b será novamente uma variável aleatória Gaussiana com média 0, mas será muito mais aguda que antes. Suponha, como fizemos anteriormente, que 500 das entradas são zero e 500 são 1. Então é fácil mostrar (veja o gráfico abaixo) que z tem uma distribuição Gaussiana com média 0 e desvio padrão igual a 1,22…(raiz quadrada de 3/2). Isso é muito mais agudo do que antes, tanto que até o gráfico abaixo subestima a situação, já que precisamos redimensionar o eixo vertical, quando comparado ao gráfico anterior:

 

rede3

 

É muito menos provável que tal neurônio sature e, correspondentemente, é muito menos provável que tenha problemas com a lentidão do aprendizado.

Eu afirmei acima que nós continuaremos a inicializar os vieses como antes, como variáveis ​​aleatórias Gaussianas com uma média de 0 e um desvio padrão de 1. Isto não tem problema, pois é pouco provável que nossos neurônios vão saturar. Na verdade, não importa muito como inicializamos os vieses, desde que evitemos o problema com a saturação dos neurônios. Algumas pessoas vão tão longe a ponto de inicializar todos os vieses com 0, e dependem da descida de gradiente para aprender vieses apropriados. Mas como é improvável que faça muita diferença, continuaremos com o mesmo procedimento de inicialização de antes.

Vamos comparar os resultados para as nossas abordagens antiga e nova para inicialização de peso, usando a tarefa de classificação de dígitos MNIST. Como antes, usaremos 30 neurônios ocultos, um tamanho de mini-lote de 10, um parâmetro de regularização λ = 5.0 e a função de custo de entropia cruzada. Diminuiremos ligeiramente a taxa de aprendizado de η = 0,5 para 0,1, pois isso torna os resultados um pouco mais visíveis nos gráficos. Podemos treinar usando o antigo método de inicialização de peso:

 

rede4

 

Também podemos treinar usando a nova abordagem para inicializar o peso. Na verdade, isso é ainda mais fácil, já que a maneira padrão de inicializar os pesos da rede2 é usar essa nova abordagem. Isso significa que podemos omitir a chamada net.large_weight_initializer () acima:

 

rede5

 

Plotando os resultados, obtemos:

 

rede6

 

Em ambos os casos, acabamos com uma precisão de classificação um pouco acima de 96%. A precisão final da classificação é quase exatamente a mesma nos dois casos, mas a nova técnica de inicialização é muito, muito mais rápida. No final da primeira época de treinamento, a antiga abordagem de inicialização de peso tem uma precisão de classificação abaixo de 87%, enquanto a nova abordagem já chega a quase 93%. O que parece estar acontecendo é que nossa nova abordagem para a inicialização do peso nos leva a um processo muito melhor, o que nos permite obter bons resultados muito mais rapidamente. O mesmo fenômeno também é visto se traçarmos resultados com 100 neurônios ocultos:

 

rede7

 

Neste caso, as duas curvas não se encontram. No entanto, nossas experiências sugerem que, com apenas mais algumas épocas de treinamento (não mostradas), as precisões se tornam quase exatamente as mesmas. Portanto, com base nesses experimentos, parece que a inicialização do peso aprimorado apenas acelera o aprendizado, não altera o desempenho final de nossas redes. No entanto, veremos mais a frente alguns exemplos de redes neurais em que o comportamento de longo prazo é significativamente melhor com a inicialização de peso usando:

 

form

 

Assim, não é apenas a velocidade de aprendizado que é melhorada, mas também o desempenho final.

A abordagem acima para a inicialização do peso ajuda a melhorar a maneira como nossas redes neurais aprendem. Outras técnicas para inicialização de peso também foram propostas, muitas baseadas nessa ideia básica. Não vamos rever as outras abordagens aqui, já que a descrita anteriormente funciona bem o suficiente para nossos propósitos. Se você estiver interessado em pesquisar mais, recomendamos a leitura das páginas 14 e 15 de um artigo de 2012 de Yoshua Bengio (um dos padrinhos do Deep Learning), bem como as referências nele contidas: Practical Recommendations for Gradient-Based Training of Deep Architectures. 

Para aplicar esses conceitos na prática com Linguagem Python, acesse aqui: Deep Learning Para Aplicações de Inteligência Artificial. 

Até o próximo capítulo!

Referências:

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Machine Learning

Deep Learning Book

Capítulo 15 – Algoritmo Backpropagation Parte 2 – Treinamento de Redes Neurais

by

O backpropagation é indiscutivelmente o algoritmo mais importante na história das redes neurais – sem backpropagation (eficiente), seria impossível treinar redes de aprendizagem profunda da forma que vemos hoje. O backpropagation pode ser considerado a pedra angular das redes neurais modernas e aprendizagem profunda. Neste capítulo, vamos compreender como o backpropagation é usado no treinamento das redes neurais: Algoritmo Backpropagation Parte 2 – Treinamento de Redes Neurais.

O algoritmo de backpropagation consiste em duas fases:

1. O passo para frente (forward pass), onde nossas entradas são passadas através da rede e as previsões de saída obtidas (essa etapa também é conhecida como fase de propagação).

2. O passo para trás (backward pass), onde calculamos o gradiente da função de perda na camada final (ou seja, camada de previsão) da rede e usamos esse gradiente para aplicar recursivamente a regra da cadeia (chain rule) para atualizar os pesos em nossa rede (etapa também conhecida como fase de atualização de pesos ou retro-propagação).

Vamos analisar cada uma dessas fases e compreender como funciona o backpropagation no treinamento nas redes neurais. No próximo capítulo, voltaremos ao script em Python para compreender como é a implementação do algoritmo. Let’s begin!

Forward Pass

O propósito do passo para frente é propagar nossas entradas (os dados de entrada) através da rede aplicando uma série de dot products (multiplicação entre os vetores) e ativações até chegarmos à camada de saída da rede (ou seja, nossas previsões). Para visualizar esse processo, vamos primeiro considerar a tabela abaixo. Podemos ver que cada entrada X na matriz é 2-dim (2 dimensões), onde cada ponto de dado é representado por dois números. Por exemplo, o primeiro ponto de dado é representado pelo vetor de recursos (0, 0), o segundo ponto de dado por (0, 1), etc. Em seguida, temos nossos valores de saída Y como a coluna da direita. Nossos valores de saída são os rótulos de classe. Dada uma entrada da matriz, nosso objetivo é prever corretamente o valor de saída desejado. Em resumo, X representa as entradas e Y a saída.

 

table

 

Para obter uma precisão de classificação perfeita nesse problema, precisamos de uma rede neural feedforward com pelo menos uma camada oculta. Podemos então começar com uma arquitetura de 2-2-1 conforme a imagem abaixo.

 

rede1

 

Este é um bom começo, no entanto, estamos esquecendo de incluir o bias. Existem duas maneiras de incluir o bias b em nossa rede. Nós podemos:

1. Usar uma variável separada.
2. Tratar o bias como um parâmetro treinável dentro da matriz, inserindo uma coluna de 1s nos vetores de recursos.

Inserir uma coluna de 1s no nosso vetor de recursos é feito de forma programática, mas para garantir a didática, vamos atualizar nossa matriz para ver isso explicitamente, conforme tabela abaixo. Como você pode ver, uma coluna de 1s foi adicionada aos nossos vetores de recursos. Na prática você pode inserir essa coluna em qualquer lugar que desejar, mas normalmente a colocamos como a primeira entrada no vetor de recursos ou a última entrada no vetor de recursos.

 

table2

 

Como nós mudamos o tamanho do nosso vetor de recursos de entrada (normalmente o que é realizado dentro da implementação da rede em si, para que não seja necessário modificar explicitamente a nossa matriz), isso muda nossa arquitetura de rede de 2-2-1 para uma arquitetura 3-3-1, conforme imagem abaixo. Ainda nos referimos a essa arquitetura de rede como 2-2-1, mas quando se trata de implementação, na verdade, é 3-3-1 devido à adição do termo de bias incorporado na matriz.

rede2

Finalmente, lembre-se de que tanto nossa camada de entrada quanto todas as camadas ocultas exigem um termo de bias. No entanto, a camada de saída final não requer um bias. O bias agora é um parâmetro treinável dentro da matriz de peso, tornando o treinamento mais eficiente e substancialmente mais fácil de implementar. Para ver o forward pass em ação, primeiro inicializamos os pesos em nossa rede, conforme figura abaixo. Observe como cada seta na matriz de peso tem um valor associado a ela – esse é o valor de peso atual para um determinado nó e significa o valor em que uma determinada entrada é amplificada ou diminuída. Este valor de peso será então atualizado durante a fase de backpropgation (lembre-se que ainda estamos no forward pass). Existem várias formas de inicializar o vetor de pesos e isso pode influenciar diretamente no treinamento da rede, como veremos mais abaixo.

Na extrema esquerda da figura abaixo, apresentamos o vetor de recursos (0, 1, 1) e também o valor de saída 1 para a rede, pois depois precisamos calcular os erros de previsão. Aqui podemos ver que 0,1 e 1 foram atribuídos aos três nós de entrada na rede. Para propagar os valores através da rede e obter a classificação final, nós precisamos do dot product entre as entradas e os valores de peso, seguido pela aplicação de um função de ativação (neste caso, a função sigmóide s). Vamos calcular as entradas para os três nós nas camadas ocultas:

1. s ((0 x 0.351) + (1 x 1.076) + (1 x 1.116)) = 0.899

2. s ((0 x 0.097) + (1 x 0.165)+(1 x 0.542)) = 0.593

3. s ((0x 0.457) + (1 x 0.165)+(1 x 0.331)) = 0.378

 

rede3

 

 

Observando os valores dos nós das camadas ocultas (camadas do meio), podemos ver que os nós foram atualizados para refletir nossa computação. Agora temos nossas entradas para os nós da camada oculta. Para calcular a previsão de saída, uma vez mais usamos o dot product seguido por uma ativação sigmóide:

s ((0.899 x 0.383) + (0.593 x – 0.327) + (0.378 x -0.329)) = 0.506

A saída da rede é, portanto, 0.506. Podemos aplicar uma função de etapa (step function) para determinar se a saída é a classificação correta ou não:

 

saida

 

Aplicando a step function com saida = 0.506, vemos que nossa rede prevê 1 que é, de fato, o rótulo de classe correto. No entanto, a nossa rede não está muito confiante neste rótulo de classe. O valor previsto 0.506 está muito próximo do limite da etapa. Idealmente, esta previsão deve ser mais próxima de 0.98 ou 0.99., implicando que a nossa rede realmente aprendeu o padrão no conjunto de dados. Para que nossa rede realmente “aprenda”, precisamos aplicar o backpropagation.

Backpropagation

Para qualquer problema de aprendizagem supervisionada, nós selecionamos pesos que fornecem a estimativa ótima de uma função que modela nossos dados de treinamento. Em outras palavras, queremos encontrar um conjunto de pesos W que minimize a saída de J(W), onde J(W) é a função de perda, ou o erro da rede. Nos capítulos anteriores, discutimos o algoritmo de gradiente descendente, em que atualizamos cada peso por alguma redução escalar negativa da derivada do erro em relação a esse peso. Se optarmos por usar gradiente descendente (ou quase qualquer outro algoritmo de otimização convexo), precisamos encontrar as derivadas na forma numérica.

O objetivo do backpropagation é otimizar os pesos para que a rede neural possa aprender a mapear corretamente as entradas para as saídas.

Para outros algoritmos de aprendizado de máquina, como regressão logística ou regressão linear, o cálculo das derivadas é uma aplicação elementar de diferenciação. Isso ocorre porque as saídas desses modelos são apenas as entradas multiplicadas por alguns pesos escolhidos e, no máximo, alimentados por uma única função de ativação (a função sigmóide na regressão logística). O mesmo, no entanto, não pode ser dito para redes neurais. Para demonstrar isso, aqui está um diagrama de uma rede neural de dupla camada:

 

diam

 

Como você pode ver, cada neurônio é uma função do anterior conectado a ele. Em outras palavras, se alguém alterasse o valor de w1, os neurônios “hidden 1” e “hidden 2” (e, finalmente, a saída) mudariam. Devido a essa noção de dependências funcionais, podemos formular matematicamente a saída como uma função composta extensiva:

 

func

 

ou simplesmente:

 

func2

 

Para aplicar o algoritmo de backpropagation, nossa função de ativação deve ser diferenciável, de modo que possamos calcular a derivada parcial do erro em relação a um dado peso wi,j, loss(E), saída de nó oj e saída de rede j.

 

derivada

 

Aqui, a saída é uma função composta dos pesos, entradas e função (ou funções) de ativação. É importante perceber que as unidades / nós ocultos são simplesmente cálculos intermediários que, na realidade, podem ser reduzidos a cálculos da camada de entrada. Se fôssemos então tirar a derivada da função com relação a algum peso arbitrário (por exemplo, w1), aplicaríamos iterativamente a regra da cadeia (da qual eu tenho certeza que você se lembra do capítulo anterior). O resultado seria semelhante ao seguinte:

 

func3

 

Agora, vamos anexar mais uma operação à cauda da nossa rede neural. Esta operação irá calcular e retornar o erro – usando a função de custo – da nossa saída:

 

func4

 

Tudo o que fizemos foi adicionar outra dependência funcional; nosso erro é agora uma função da saída e, portanto, uma função da entrada, pesos e função de ativação. Se fôssemos calcular a derivada do erro com qualquer peso arbitrário (novamente, escolheríamos w1), o resultado seria:

 

func5

 

Cada uma dessas derivações pode ser simplificada, uma vez que escolhemos uma função de ativação e erro, de modo que todo o resultado represente um valor numérico. Nesse ponto, qualquer abstração foi removida e a derivada de erro pode ser usada na descida do gradiente (como discutido anteriormente aqui no livro) para melhorar iterativamente o peso. Calculamos as derivadas de erro w.r.t. para todos os outros pesos na rede e aplicamos gradiente descendente da mesma maneira. Isso é backpropagation – simplesmente o cálculo de derivadas que são alimentadas para um algoritmo de otimização convexa. Chamamos isso de “retropropagação” porque estamos usando o erro de saída para atualizar os pesos, tomando passos iterativos usando a regra da cadeia até que alcancemos o valor de peso ideal.

Depois de compreender o funcionamento do algoritmo backpropagation, você percebe sua simplicidade. Claro, a aritmética/cálculos reais podem ser difíceis, mas esse processo é tratado pelos nossos computadores. Na realidade, o backpropagation é apenas uma aplicação da regra da cadeia (chain rule). Como as redes neurais são estruturas de modelo de aprendizado de máquina multicamadas complicadas, cada peso “contribui” para o erro geral de uma maneira mais complexa e, portanto, as derivadas reais exigem muito esforço para serem produzidas. No entanto, uma vez que passamos pelo cálculo, o backpropagation das redes neurais é equivalente à descida de gradiente típica para regressão logística / linear.

Assim, como regra geral de atualizações de peso, podemos usar a Regra Delta (Delta Rule):

 

Novo Peso = Peso Antigo – Derivada * Taxa de Aprendizagem

 

A taxa de aprendizagem (learning rate) é introduzida como uma constante (geralmente muito pequena), a fim de forçar o peso a ser atualizado de forma suave e lenta (para evitar grandes passos e comportamento caótico).

Para validar esta equação:

  • Se a Derivada for positiva, isso significa que um aumento no peso aumentará o erro, portanto, o novo peso deverá ser menor.
  • Se a Derivada é negativa, isso significa que um aumento no peso diminuirá o erro, portanto, precisamos aumentar os pesos.
  • Se a Derivada é 0, significa que estamos em um mínimo estável. Assim, nenhuma atualização nos pesos é necessária -> chegamos a um estado estável.

Existem vários métodos de atualização de peso. Esses métodos são frequentemente chamados de otimizadores. A regra delta é a mais simples e intuitiva, no entanto, possui várias desvantagens. Confira nas referências ao final do capítulo, um excelente artigo sobre otimizadores.

Como atualizamos os pesos com uma pequena etapa delta de cada vez, serão necessárias várias iterações para ocorrer o aprendizado. Na rede neural, após cada iteração, a força de descida do gradiente atualiza os pesos para um valor cada vez menor da função de perda global. A atualização de peso na rede neural é guiada pela força do gradiente descendente sobre o erro.

Quantas iterações são necessárias para convergir (ou seja, alcançar uma função de perda mínima global)? Isso vai depender de diversos fatores:

  • Depende de quão forte é a taxa de aprendizado que estamos aplicando. Alta taxa de aprendizado significa aprendizado mais rápido, mas com maior chance de instabilidade.
  • Depende também dos hyperparâmetros da rede (quantas camadas, quão complexas são as funções não-lineares, etc..). Quanto mais variáveis, mais leva tempo para convergir, mas a precisão tende a ser maior.
  • Depende do uso do método de otimização, pois algumas regras de atualização de peso são comprovadamente mais rápidas do que outras.
  • Depende da inicialização aleatória da rede. Talvez com alguma sorte você inicie a rede com pesos quase ideais e esteja a apenas um passo da solução ideal. Mas o contrário também pode ocorrer.
  • Depende da qualidade do conjunto de treinamento. Se a entrada e a saída não tiverem correlação entre si, a rede neural não fará mágica e não poderá aprender uma correlação aleatória.

Ou seja, treinar uma rede neural não é tarefa simples. Imagine agora treinar uma rede profunda, com várias camadas intermediárias e milhões ou mesmo bilhões de pontos de dados e você compreende o quão trabalhoso isso pode ser e quantas decisões devem ser tomadas pelo Cientista de Dados ou Engenheiro de IA. E aprender a trabalhar de forma profissional, requer tempo, dedicação e preparo e melhor ainda se isso puder ser 100% em português para acelerar seu aprendizado. Construir aplicações de IA é uma habilidade com demanda cada vez maior no mercado.

Agora que você já compreende como funciona o backpropagation, podemos retornar ao código Python e ver tudo isso funcionando na prática. Mas isso é assunto para o próximo capítulo!

Referências:

Formação Engenheiro de IA

Dot Product 

How the backpropagation algorithm works

Delta Rule

An overview of gradient descent optimization algorithms

Neural Networks & The Backpropagation Algorithm, Explained

Derivada

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Understanding Activation Functions in Neural Networks

Redes Neurais, princípios e práticas

An overview of gradient descent optimization algorithms

Optimization: Stochastic Gradient Descent

Gradient Descent vs Stochastic Gradient Descent vs Mini-Batch Learning

Deep Learning Book

Capítulo 10 – As Principais Arquiteturas de Redes Neurais

by

O Aprendizado de Máquina (Machine Learning) é necessário para resolver tarefas que são muito complexas para os humanos. Algumas tarefas são tão complexas que é impraticável, senão impossível, que os seres humanos consigam explicar todas as nuances envolvidas. Então, em vez disso, fornecemos uma grande quantidade de dados para um algoritmo de aprendizado de máquina e deixamos que o algoritmo funcione, explorando esses dados e buscando um modelo que alcance o que os Cientistas de Dados e Engenheiros de IA determinaram como objetivo. Vejamos estes dois exemplos:

– É muito difícil escrever programas que solucionem problemas como reconhecer um objeto tridimensional a partir de um novo ponto de vista em novas condições de iluminação em uma cena desordenada. Nós não sabemos qual programa de computador escrever porque não sabemos como ocorre o processo em nosso cérebro. Mesmo se tivéssemos uma boa ideia sobre como fazê-lo, o programa poderia ser incrivelmente complicado.

– É difícil escrever um programa para calcular a probabilidade de uma transação de cartão de crédito ser fraudulenta. Pode não haver regras que sejam simples e confiáveis. Precisamos combinar um número muito grande de regras fracas. A fraude é um alvo em movimento, mas o programa precisa continuar mudando.

É onde Machine Learning pode ser aplicado com sucesso. Em vez de escrever um programa à mão para cada tarefa específica, nós coletamos muitos exemplos que especificam a saída correta para uma determinada entrada. Um algoritmo de aprendizagem de máquina recebe esses exemplos e produz um programa que faz o trabalho. O programa produzido pelo algoritmo de aprendizagem pode parecer muito diferente de um programa típico escrito à mão. Pode conter milhões de números. Se o fizermos corretamente, o programa funciona para novos casos (novos dados). Se os dados mudarem, o programa também pode mudar ao treinar em novos dados. E com a redução de custos de computação (principalmente usando processamento em nuvem), grande quantidade de dados (Big Data) e processamento paralelo em GPU, temos as condições perfeitas para a evolução de Machine Learning. O maior problema, por incrível que pareça, será a falta de profissionais qualificados em número suficiente para atender as demandas do mercado.

Alguns exemplos de tarefas melhor resolvidas pela aprendizagem de máquina incluem:

  • Reconhecimento de padrões: objetos em cenas reais, identidades faciais ou expressões faciais, palavras escritas ou faladas.
  • Detecção de anomalias: sequências incomuns de transações de cartão de crédito, padrões incomuns de leituras de sensores em máquinas de uma indústria têxtil.
  • Previsão: preços de ações futuros ou taxas de câmbio, quais filmes uma pessoa gostaria de assistir, previsão de vendas.

Machine Learning é um campo abrangente dentro da Inteligência Artificial. Mas uma sub-área de Machine Learning, o Deep Learning (ou Redes Neurais Profundas), vem conseguindo resultados no estado da arte para as tarefas acima mencionadas. Neste capítulo você encontra As 10 Principais Arquiteturas de Redes Neurais, dentre elas as principais arquiteturas de Deep Learning.

1- Redes Multilayer Perceptrons

O Perceptron, conforme estudamos nos capítulos anteriores, é um algoritmo simples destinado a realizar a classificação binária; isto é, prevê se a entrada pertence a uma determinada categoria de interesse ou não: fraude ou não_fraude, gato ou não_gato.

Multilayer Perceptrons (MLP)

Um Perceptron é um classificador linear; ou seja, é um algoritmo que classifica a entrada separando duas categorias com uma linha reta. A entrada geralmente é um vetor de recursos x multiplicado por pesos w e adicionado a um viés (ou bias) b. Aqui um exemplo do Perceptron: y = w * x + b. Um Perceptron produz uma única saída com base em várias entradas de valor real, formando uma combinação linear usando os pesos (e às vezes passando a saída através de uma função de ativação não linear).

Rosenblatt construiu um Perceptron de uma camada. Ou seja, seu algoritmo não inclui múltiplas camadas, o que permite que as redes neurais modelem uma hierarquia de recursos. Isso impede que o Perceptron consiga realizar classificação não linear, como a função XOR (um disparador do operador XOR quando a entrada exibe uma característica ou outra, mas não ambas, significa “OR exclusivo” “), como Minsky e Papert mostraram em seu livro.

Um Multilayer Perceptron (MLP) é uma rede neural artificial composta por mais de um Perceptron. Eles são compostos por uma camada de entrada para receber o sinal, uma camada de saída que toma uma decisão ou previsão sobre a entrada, e entre esses dois, um número arbitrário de camadas ocultas que são o verdadeiro mecanismo computacional do MLP. MLPs com uma camada oculta são capazes de aproximar qualquer função contínua.

O Multilayer Perceptron é uma espécie de “Hello World” da aprendizagem profunda: uma boa forma de começar quando você está aprendendo sobre Deep Learning.

Os MLPs são frequentemente aplicados a problemas de aprendizagem supervisionados: treinam em um conjunto de pares entrada-saída e aprendem a modelar a correlação (ou dependências) entre essas entradas e saídas. O treinamento envolve o ajuste dos parâmetros, ou os pesos e bias, do modelo para minimizar o erro. O backpropagation é usado para fazer os ajustes dos pesos e de bias em relação ao erro, e o próprio erro pode ser medido de várias maneiras, inclusive pelo erro quadrático médio (MSE – Mean Squared Error).

As redes feed forward, como MLPs, são como ping-pong. Elas são principalmente envolvidas em dois movimentos, uma constante de ida e volta.  Na passagem para a frente, o fluxo de sinal se move da camada de entrada através das camadas ocultas para a camada de saída e a decisão da camada de saída é medida em relação às saídas esperadas.

Na passagem para trás, usando o backpropagation e a regra da cadeia (Chain Rule), derivadas parciais da função de erro dos vários pesos e bias são reproduzidos através do MLP. Esse ato de diferenciação nos dá um gradiente, ao longo do qual os parâmetros podem ser ajustados à medida que movem o MLP um passo mais perto do erro mínimo. Isso pode ser feito com qualquer algoritmo de otimização baseado em gradiente, como descida estocástica do gradiente. A rede continua jogando aquele jogo de ping-pong até que o erro não possa mais ser reduzido (chegou ao mínimo possível). Este estado é conhecido como convergência.

2- Redes Neurais Convolucionais

Em 1998, Yann LeCun e seus colaboradores desenvolveram um reconhecedor, realmente bom, para dígitos manuscritos chamado LeNet. Ele usou o backpropagation em uma rede feed forward com muitas camadas ocultas, muitos mapas de unidades replicadas em cada camada, agrupando as saídas de unidades próximas, formando uma rede ampla que pode lidar com vários caracteres ao mesmo tempo, mesmo se eles se sobrepõem e uma inteligente maneira de treinar um sistema completo, não apenas um reconhecedor. Mais tarde, esta arquitetura foi formalizada sob o nome de redes neurais convolucionais.

As Redes Neurais Convolucionais (ConvNets ou CNNs) são redes neurais artificiais profundas que podem ser usadas para classificar imagens, agrupá-las por similaridade (busca de fotos) e realizar reconhecimento de objetos dentro de cenas. São algoritmos que podem identificar rostos, indivíduos, sinais de rua, cenouras, ornitorrincos e muitos outros aspectos dos dados visuais.

As redes convolucionais realizam o reconhecimento óptico de caracteres (OCR) para digitalizar texto e tornar possível o processamento de linguagem natural em documentos analógicos e manuscritos, onde as imagens são símbolos a serem transcritos. CNNs também podem ser aplicadas a arquivos de áudio quando estes são representados visualmente como um espectrograma. Mais recentemente, as redes convolucionais foram aplicadas diretamente à análise de texto, bem como dados gráficos.

A eficácia das redes convolucionais no reconhecimento de imagem é uma das principais razões pelas quais o mundo testemunhou a eficácia do aprendizado profundo. Este tipo de rede está impulsionando grandes avanços em Visão Computacional, que tem aplicações óbvias em carros autônomos, robótica, drones, segurança, diagnósticos médicos e tratamentos para deficientes visuais.

As redes convolucionais ingerem e processam imagens como tensores e tensores são matrizes de números com várias dimensões. Eles podem ser difíceis de visualizar, então vamos abordá-los por analogia. Um escalar é apenas um número, como 7; um vetor é uma lista de números (por exemplo, [7,8,9]); e uma matriz é uma grade retangular de números que ocupam várias linhas e colunas como uma planilha. Geometricamente, se um escalar é um ponto de dimensão zero, então um vetor é uma linha unidimensional, uma matriz é um plano bidimensional, uma pilha de matrizes é um cubo tridimensional e quando cada elemento dessas matrizes tem uma pilha de mapas de recursos ligados a ele, você entra na quarta dimensão. Calma, não se desespere (ainda). Veremos isso mais a frente com calma, quando estudarmos exclusivamente esta arquitetura. Em nossos cursos na Data Science Academy incluímos aulas completas sobre Álgebra Linear, onde escalares, vetores, matrizes e tensores são estudados na teoria e prática, pois este conhecimento é fundamental na construção de redes neurais profundas.

A primeira coisa a saber sobre redes convolucionais é que elas não percebem imagens como os humanos. Portanto, você terá que pensar de uma maneira diferente sobre o que uma imagem significa quando é alimentada e processada por uma rede convolucional.

CNN

As redes convolucionais percebem imagens como volumes; isto é, objetos tridimensionais, em vez de estruturas planas a serem medidas apenas por largura e altura. Isso porque as imagens de cores digitais têm uma codificação vermelho-verde-azul (RGB – Red-Green-Blue), misturando essas três cores para produzir o espectro de cores que os seres humanos percebem. Uma rede convolucional recebe imagens como três estratos separados de cores empilhados um em cima do outro.

Assim, uma rede convolucional recebe uma imagem como uma caixa retangular cuja largura e altura são medidas pelo número de pixels ao longo dessas dimensões e cuja profundidade é de três camadas profundas, uma para cada letra em RGB. Essas camadas de profundidade são referidas como canais.

À medida que as imagens se movem através de uma rede convolucional, descrevemos em termos de volumes de entrada e saída, expressando-as matematicamente como matrizes de múltiplas dimensões dessa forma: 30x30x3. De camada em camada, suas dimensões mudam à medida que atravessam a rede neural convolucional até gerar uma série de probabilidades na camada de saída, sendo uma probabilidade para cada possível classe de saída. Aquela com maior probabilidade, será a classe definida para a imagem de entrada, um pássaro por exemplo.

Você precisará prestar muita atenção às medidas de cada dimensão do volume da imagem, porque elas são a base das operações de álgebra linear usadas para processar imagens. Poderíamos dedicar dois capítulos inteiros somente a esta arquitetura. Aliás, é o que faremos mais à frente aqui no livro e o que já fazemos na prática aqui.

3- Redes Neurais Recorrentes

As redes recorrentes são um poderoso conjunto de algoritmos de redes neurais artificiais especialmente úteis para o processamento de dados sequenciais, como som, dados de séries temporais ou linguagem natural. Uma versão de redes recorrentes foi usada pelo DeepMind no projeto de videogames com agentes autônomos.

As redes recorrentes diferem das redes feed forward porque incluem um loop de feedback, pelo qual a saída do passo n-1 é alimentada de volta à rede para afetar o resultado do passo n, e assim por diante para cada etapa subsequente. Por exemplo, se uma rede é exposta a uma palavra letra por letra, e é solicitado a adivinhar cada letra a seguir, a primeira letra de uma palavra ajudará a determinar o que uma rede recorrente pensa que a segunda letra pode ser.

Isso difere de uma rede feed forward, que aprende a classificar cada número manuscrito por exemplo, independentemente, e de acordo com os pixels de que é exposto a partir de um único exemplo, sem se referir ao exemplo anterior para ajustar suas previsões. As redes feed forward aceitam uma entrada por vez e produzem uma saída. As redes recorrentes não enfrentam a mesma restrição um-para-um.

Embora algumas formas de dados, como imagens, não pareçam ser sequenciais, elas podem ser entendidas como sequências quando alimentadas em uma rede recorrente. Considere uma imagem de uma palavra manuscrita. Assim como as redes recorrentes processam a escrita manual, convertendo cada imagem em uma letra e usando o início de uma palavra para adivinhar como essa palavra terminará, então as redes podem tratar parte de qualquer imagem como letras em uma sequência. Uma rede neural que percorre uma imagem grande pode aprender a partir de cada região, o que as regiões vizinhas, são mais prováveis ​​de ser.

Redes Neurais Recorrentes

As redes recorrentes e as redes feed forward “lembram” algo sobre o mundo, modelando os dados que estão expostos. Mas elas se lembram de maneiras muito diferentes. Após o treinamento, a rede feed forward produz um modelo estático dos dados e esse modelo pode então aceitar novos exemplos e classificá-los ou agrupá-los com precisão.

Em contraste, as redes recorrentes produzem modelos dinâmicos – ou seja, modelos que mudam ao longo do tempo – de formas que produzem classificações precisas dependentes do contexto dos exemplos que estão expostos.

Para ser preciso, um modelo recorrente inclui o estado oculto que determinou a classificação anterior em uma série. Em cada etapa subsequente, esse estado oculto é combinado com os dados de entrada do novo passo para produzir a) um novo estado oculto e, em seguida, b) uma nova classificação. Cada estado oculto é reciclado para produzir seu sucessor modificado.

As memórias humanas também são conscientes do contexto, reciclando a consciência de estados anteriores para interpretar corretamente novos dados. Por exemplo, vamos considerar dois indivíduos. Um está ciente de que ele está perto da casa de Bob. O outro está ciente de que entrou em um avião. Eles interpretarão os sons “Oi Bob!” de duas formas muito diferentes, precisamente porque retém um estado oculto afetado por suas memórias de curto prazo e sensações precedentes.

Diferentes lembranças de curto prazo devem ser recontadas em momentos diferentes, a fim de atribuir o significado certo à entrada atual. Algumas dessas memórias terão sido forjadas recentemente e outras memórias terão forjado muitos passos antes de serem necessários. A rede recorrente que efetivamente associa memórias e entrada remota no tempo é chamada de Memória de Longo Prazo (LSTM), a qual veremos em seguida.

4- Long Short-Term Memory (LSTM)

Em meados dos anos 90, a proposta dos pesquisadores alemães Sepp Hochreiter e Juergen Schmidhuber apresentou uma variação da rede recorrente com as chamadas unidades de Long Short-Term Memory, como uma solução para o problema do vanishing gradient, problema comum em redes neurais recorrentes.

Os LSTMs ajudam a preservar o erro que pode ser copiado por tempo e camadas. Ao manter um erro mais constante, eles permitem que as redes recorrentes continuem aprendendo durante vários passos de tempo (mais de 1000), abrindo assim um canal para vincular causas e efeitos remotamente. Este é um dos desafios centrais para a aprendizagem de máquina e a IA, uma vez que os algoritmos são frequentemente confrontados por ambientes onde os sinais de recompensa são escassos e atrasados, como a própria vida. (Os pensadores religiosos abordaram este mesmo problema com ideias de karma ou recompensas divinas, teorizando consequências invisíveis e distantes para nossas ações).

Os LSTMs contêm informações fora do fluxo normal da rede recorrente em uma célula fechada. As informações podem ser armazenadas, escritas ou lidas a partir de uma célula, como dados na memória de um computador. A célula toma decisões sobre o que armazenar, e quando permitir leituras, gravações e exclusões, através de portões abertos e fechados. Ao contrário do armazenamento digital em computadores, no entanto, esses portões são analógicos, implementados com a multiplicação de elementos por sigmóides, que estão todos na faixa de 0-1. Analógico tem a vantagem sobre o digital de ser diferenciável e, portanto, adequado para backpropagation.

Esses portões atuam sobre os sinais que recebem e, de forma semelhante aos nós da rede neural, eles bloqueiam ou transmitem informações com base em sua força e importação, que eles filtram com seus próprios conjuntos de pesos. Esses pesos, como os pesos que modulam a entrada e estados ocultos, são ajustados através do processo de aprendizagem das redes recorrentes. Ou seja, as células aprendem quando permitir que os dados entrem, saiam ou sejam excluídos através do processo iterativo de fazer suposições, calculando o erro durante o backpropagation e ajustando pesos através da descida do gradiente.

O diagrama abaixo ilustra como os dados fluem através de uma célula de memória e são controlados por seus portões.

Long Short-Term Memory

Os LSTM’s possuem muitas aplicações práticas, incluindo processamento de linguagem natural, geração automática de texto e análise de séries temporais. Caso queira ver esses exemplos na prática, clique aqui. Teremos um capítulo inteiro dedicado aos LSTM’s aqui no livro.

5- Redes de Hopfield

Redes recorrentes de unidades não lineares geralmente são muito difíceis de analisar. Elas podem se comportar de muitas maneiras diferentes: se estabelecer em um estado estável, oscilar ou seguir trajetórias caóticas que não podem ser preditas no futuro. Uma Rede Hopfield é composta por unidades de limite binário com conexões recorrentes entre elas. Em 1982, John Hopfield percebeu que, se as conexões são simétricas, existe uma função de energia global. Cada “configuração” binária de toda a rede possui energia, enquanto a regra de decisão do limite binário faz com que a rede se conforme com um mínimo desta função de energia. Uma excelente maneira de usar esse tipo de computação é usar memórias como energia mínima para a rede neural. Usar mínimos de energia para representar memórias resulta em uma memória endereçável ao conteúdo. Um item pode ser acessado por apenas conhecer parte do seu conteúdo. É robusto contra danos no hardware.

Hopfield

Cada vez que memorizamos uma configuração, esperamos criar um novo mínimo de energia. Mas e se dois mínimos próximos estão em um local intermediário? Isso limita a capacidade de uma Rede Hopfield. Então, como aumentamos a capacidade de uma Rede Hopfield? Os físicos adoram a ideia de que a matemática que eles já conhecem pode explicar como o cérebro funciona. Muitos artigos foram publicados em revistas de física sobre Redes Hopfield e sua capacidade de armazenamento. Eventualmente, Elizabeth Gardner descobriu que havia uma regra de armazenamento muito melhor que usa a capacidade total dos pesos. Em vez de tentar armazenar vetores de uma só vez, ela percorreu o conjunto de treinamento muitas vezes e usou o procedimento de convergência Perceptron para treinar cada unidade para ter o estado correto, dado os estados de todas as outras unidades nesse vetor. Os estatísticos chamam essa técnica de “pseudo-probabilidade”.

Existe outro papel computacional para as Redes Hopfield. Em vez de usar a rede para armazenar memórias, usamos para construir interpretações de entrada sensorial. A entrada é representada pelas unidades visíveis, a interpretação é representada pelos estados das unidades ocultas e o erro da interpretação é representado pela energia.

6- Máquinas de Boltzmann

Uma Máquina de Boltzmann é um tipo de rede neural recorrente estocástica. Pode ser visto como a contrapartida estocástica e generativa das Redes Hopfield. Foi uma das primeiras redes neurais capazes de aprender representações internas e é capaz de representar e resolver problemas combinatórios difíceis.

O objetivo do aprendizado do algoritmo da Máquina de Boltzmann é maximizar o produto das probabilidades que a Máquina de Boltzmann atribui aos vetores binários no conjunto de treinamento. Isso equivale a maximizar a soma das probabilidades de log que a Máquina de Boltzmann atribui aos vetores de treinamento. Também é equivalente a maximizar a probabilidade de obtermos exatamente os N casos de treinamento se fizéssemos o seguinte: 1) Deixar a rede se estabelecer em sua distribuição estacionária no tempo N diferente, sem entrada externa e 2) Mudar o vetor visível uma vez em cada passada.

Um procedimento eficiente de aprendizado de mini-lote foi proposto para as Máquinas de Boltzmann por Salakhutdinov e Hinton em 2012.

Boltzmann Machine Network

Em uma Máquina de Boltzmann geral, as atualizações estocásticas de unidades precisam ser sequenciais. Existe uma arquitetura especial que permite alternar atualizações paralelas que são muito mais eficientes (sem conexões dentro de uma camada, sem conexões de camada ignorada). Este procedimento de mini-lote torna as atualizações da Máquina de Boltzmann mais paralelas. Isso é chamado de Deep Boltzmann Machines (DBM), uma Máquina de Boltzmann geral, mas com muitas conexões ausentes.

Em 2014, Salakhutdinov e Hinton apresentaram outra atualização para seu modelo, chamando-o de Máquinas Boltzmann Restritas. Elas restringem a conectividade para facilitar a inferência e a aprendizagem (apenas uma camada de unidades escondidas e sem conexões entre unidades ocultas). Em um RBM, é preciso apenas um passo para alcançar o equilíbrio.

7- Deep Belief Network

O backpropagation é considerado o método padrão em redes neurais artificiais para calcular a contribuição de erro de cada neurônio após processar um lote de dados (teremos um capítulo inteiro sobre isso). No entanto, existem alguns problemas importantes no backpropagation. Em primeiro lugar, requer dados de treinamento rotulados; enquanto quase todos os dados estão sem rótulos. Em segundo lugar, o tempo de aprendizagem não escala bem, o que significa que é muito lento em redes com múltiplas camadas ocultas. Em terceiro lugar, pode ficar preso em um “local optima”. Portanto, para redes profundas, o backpropagation está longe de ser ótimo.

Para superar as limitações do backpropagation, os pesquisadores consideraram o uso de abordagens de aprendizado sem supervisão. Isso ajuda a manter a eficiência e a simplicidade de usar um método de gradiente para ajustar os pesos, mas também usá-lo para modelar a estrutura da entrada sensorial. Em particular, eles ajustam os pesos para maximizar a probabilidade de um modelo gerador ter gerado a entrada sensorial. A questão é que tipo de modelo generativo devemos aprender? Pode ser um modelo baseado em energia como uma Máquina de Boltzmann? Ou um modelo causal feito de neurônios? Ou um híbrido dos dois?

Deep Belief Network

Uma Deep Belief Network pode ser definida como uma pilha de Máquinas de Boltzmann Restritas (RBM – Restricted Boltzmann Machines), em que cada camada RBM se comunica com as camadas anterior e posterior. Os nós de qualquer camada única não se comunicam lateralmente.

Esta pilha de RBMs pode terminar com uma camada Softmax para criar um classificador, ou simplesmente pode ajudar a agrupar dados não gravados em um cenário de aprendizado sem supervisão.

Com a exceção das camadas inicial e final, cada camada em uma Deep Belief Network tem uma função dupla: ela serve como a camada oculta para os nós que vem antes, e como a camada de entrada (ou “visível”) para a nós que vem depois. É uma rede construída de redes de camada única.

As Deep Belief Networks são usadas para reconhecer, agrupar e gerar imagens, sequências de vídeos e dados de captura de movimento. Outra aplicação das Deep Belief Networks é no Processamento de Linguagem Natural. Esse tipo de rede foi apresentado por Geoff Hinton e seus alunos em 2006.

8- Deep Auto-Encoders

Um Deep Auto-Encoder é composto por duas redes simétricas Deep Belief que tipicamente têm quatro ou cinco camadas rasas que representam a metade da codificação (encoder) da rede e o segundo conjunto de quatro ou cinco camadas que compõem a metade da decodificação (decoder).

As camadas são Máquinas de Boltzmann Restritas, os blocos de construção das Deep Belief Networks, com várias peculiaridades que discutiremos abaixo. Aqui está um esquema simplificado da estrutura de um Deep Auto-Encoder:

Deep Auto-Encoder

Os Deep Auto-Encoders são uma maneira muito agradável de reduzir a dimensionalidade não linear devido a alguns motivos: eles fornecem mapeamentos flexíveis em ambos os sentidos. O tempo de aprendizagem é linear (ou melhor) no número de casos de treinamento. E o modelo de codificação final é bastante compacto e rápido. No entanto, pode ser muito difícil otimizar Deep Auto-Encoders usando backpropagation. Com pequenos pesos iniciais, o gradiente do backpropagation morre. Mas temos maneiras de otimizá-las, usando o pré-treinamento camada-por-camada sem supervisão ou apenas inicializando os pesos com cuidado.

Os Deep Auto-Encoders são úteis na modelagem de tópicos ou modelagem estatística de tópicos abstratos que são distribuídos em uma coleção de documentos. Isso, por sua vez, é um passo importante em sistemas de perguntas e respostas como o IBM Watson.

Em resumo, cada documento em uma coleção é convertido em um Bag-of-Words (ou seja, um conjunto de contagens de palavras) e essas contagens de palavras são dimensionadas para decimais entre 0 e 1, o que pode ser pensado como a probabilidade de uma palavra ocorrer no documento.

As contagens de palavras em escala são então alimentadas em uma Deep Belief Network, uma pilha de Máquinas de Boltzmann Restritas, que elas mesmas são apenas um subconjunto de Autoencoders. Essas Deep Belief Networks, ou DBNs, comprimem cada documento para um conjunto de 10 números através de uma série de transformações sigmóides que o mapeiam no espaço de recursos.

O conjunto de números de cada documento, ou vetor, é então introduzido no mesmo espaço vetorial, e sua distância de qualquer outro vetor de documento medido. Em termos aproximados, os vetores de documentos próximos se enquadram no mesmo tópico. Por exemplo, um documento poderia ser a “pergunta” e outros poderiam ser as “respostas”, uma combinação que o software faria usando medidas de espaço vetorial.

Em resumo, existem agora muitas maneiras diferentes de fazer pré-treinamento camada-por-camada de recursos. Para conjuntos de dados que não possuem um grande número de casos rotulados, o pré-treinamento ajuda a aprendizagem discriminativa subsequente. Para conjuntos de dados muito grandes e rotulados, não é necessário inicializar os pesos utilizados na aprendizagem supervisionada usando pré-treinamento não supervisionado, mesmo para redes profundas. O pré-treinamento foi o primeiro bom caminho para inicializar os pesos para redes profundas, mas agora existem outras formas. Mas se construímos redes muito maiores, precisaremos de pré-treinamento novamente! 

9- Generative Adversarial Network

As Generative Adversarial Networks (GANs) são arquiteturas de redes neurais profundas compostas por duas redes, colocando uma contra a outra (daí o nome, “adversária”).

Os GANs foram introduzidos em um artigo de Ian Goodfellow e outros pesquisadores da Universidade de Montreal no Canadá, incluindo Yoshua Bengio, em 2014. Referindo-se aos GANs, o diretor de pesquisa de IA do Facebook, Yann LeCun, chamou de treinamento adversário “a ideia mais interessante nos últimos 10 anos em Machine Learning”.

O potencial de GANs é enorme, porque eles podem aprender a imitar qualquer distribuição de dados. Ou seja, os GANs podem ser ensinados a criar mundos estranhamente semelhantes aos nossos em qualquer domínio: imagens, música, fala, prosa. Eles são artistas robôs em um sentido, e sua produção é impressionante – até mesmo pungente.

Para entender os GANs, você deve saber como os algoritmos geradores funcionam, e para isso, contrastá-los com algoritmos discriminatórios é útil. Os algoritmos discriminatórios tentam classificar dados de entrada; isto é, dados os recursos de uma instância de dados, eles predizem um rótulo ou categoria a que esses dados pertencem.

Por exemplo, tendo em conta todas as palavras em um e-mail, um algoritmo discriminatório pode prever se a mensagem é spam ou not_spam. O spam é um dos rótulos, e o saco de palavras (Bag of Words) coletadas do e-mail são os recursos que constituem os dados de entrada. Quando este problema é expresso matematicamente, o rótulo é chamado y e os recursos são chamados de x. A formulação p (y | x) é usada para significar “a probabilidade de y dado x”, que neste caso seria traduzido para “a probabilidade de um email ser spam com as palavras que contém”.

Portanto, algoritmos discriminatórios mapeiam recursos para rótulos. Eles estão preocupados apenas com essa correlação. Uma maneira de pensar sobre algoritmos generativos é que eles fazem o contrário. Em vez de prever um rótulo com determinados recursos, eles tentam prever os recursos com um determinado rótulo.

A questão que um algoritmo gerador tenta responder é: assumir que este e-mail é spam, qual a probabilidade dos recursos? Enquanto os modelos discriminativos se preocupam com a relação entre y e x, os modelos generativos se preocupam com “como você obtém x”. Eles permitem que você capture p (x | y), a probabilidade de x dado y, ou a probabilidade de características oferecidas em uma classe . (Dito isto, os algoritmos geradores também podem ser usados ​​como classificadores, embora eles podem fazer mais do que categorizar dados de entrada.)

Outra maneira de pensar sobre isso é distinguir discriminativo de gerador assim:

  • Modelos discriminativos aprendem o limite entre as classes
  • Modelos generativos modelam a distribuição de classes individuais

Generative Adversarial Network

Uma rede neural, chamada de gerador, gera novas instâncias de dados, enquanto a outra, o discriminador, as avalia por autenticidade; ou seja, o discriminador decide se cada instância de dados que revisa pertence ao conjunto de dados de treinamento real ou não.

Digamos que estamos tentando fazer algo mais banal do que imitar a Mona Lisa. Vamos gerar números escritos à mão como os encontrados no conjunto de dados MNIST, que é retirado do mundo real. O objetivo do discriminador, quando mostrado uma instância do verdadeiro conjunto de dados MNIST, é reconhecê-los como autênticos.

Enquanto isso, o gerador está criando novas imagens que passa para o discriminador. Isso acontece com a esperança de que eles, também, sejam considerados autênticos, embora sejam falsos. O objetivo do gerador é gerar dígitos ​​escritos à mão por si mesmo. O objetivo do discriminador é identificar as imagens provenientes do gerador como falsas.

Aqui estão os passos que um GAN realiza:

  • O gerador recebe números aleatórios e retorna uma imagem.
  • Essa imagem gerada é alimentada no discriminador ao lado de um fluxo de imagens tiradas do conjunto de dados real.
  • O discriminador assume imagens reais e falsas e retorna probabilidades, um número entre 0 e 1, com 1 representando uma previsão de autenticidade e 0 representando falsas.

Então você tem um loop de feedback duplo:

  • O discriminador está em um loop de feedback com as imagens verdadeiras, que conhecemos.
  • O gerador está em um loop de feedback com o discriminador.

10- Deep Neural Network Capsules

No final de 2017, Geoffrey Hinton e sua equipe publicaram dois artigos que introduziram um novo tipo de rede neural chamada Capsules. Além disso, a equipe publicou um algoritmo, denominado roteamento dinâmico entre cápsulas, que permite treinar essa rede.

Para todos na comunidade de Deep Learning, esta é uma grande notícia, e por várias razões. Em primeiro lugar, Hinton é um dos fundadores do Deep Learning e um inventor de inúmeros modelos e algoritmos que hoje são amplamente utilizados. Em segundo lugar, esses artigos apresentam algo completamente novo, e isso é muito emocionante porque provavelmente estimulará a onda adicional de pesquisas e aplicativos muito inovadores.

Capsule

As Capsules introduzem um novo bloco de construção que pode ser usado na aprendizagem profunda para modelar melhor as relações hierárquicas dentro da representação do conhecimento interno de uma rede neural. A intuição por trás deles é muito simples e elegante.

Hinton e sua equipe propuseram uma maneira de treinar essa rede composta de cápsulas e treinou-a com êxito em um conjunto de dados simples, alcançando desempenho de ponta. Isso é muito encorajador. No entanto, há desafios. As implementações atuais são muito mais lentas do que outros modelos modernos de aprendizado profundo. O tempo mostrará se as redes Capsules podem ser treinadas de forma rápida e eficiente. Além disso, precisamos ver se elas funcionam bem em conjuntos de dados mais difíceis e em diferentes domínios.

Em qualquer caso, a rede Capsule é um modelo muito interessante e já funcionando, que definitivamente se desenvolverá ao longo do tempo e contribuirá para uma maior expansão de aplicações de aprendizagem profunda.

11- Redes Neurais Artificiais Baseadas em Transformadores (Transformers) 

As Redes Neurais Artificiais baseadas em Transformadores (Transformers) representam uma classe de arquiteturas de Deep Learning (aprendizado profundo) que revolucionou muitas áreas da Inteligência Artificial, especialmente o Processamento de Linguagem Natural (PLN). Introduzidas no influente artigo “Attention Is All You Need” (Atenção é Tudo o Que Você Precisa) em 2017 por pesquisadores do Google, elas se desviaram das abordagens sequenciais dominantes da época, como as Redes Neurais Recorrentes (RNNs) e LSTMs.

A principal inovação e o coração dos Transformers é o mecanismo de autoatenção (self-attention). Diferente das RNNs que processam dados (como palavras em uma frase) um após o outro em sequência, a autoatenção permite que o modelo avalie a importância de todas as outras partes da sequência de entrada ao processar uma parte específica. Essencialmente, para cada palavra (ou token) em uma frase, o modelo pode “olhar” para todas as outras palavras na mesma frase simultaneamente e determinar quais são mais relevantes para entender o significado e o contexto daquela palavra específica. Principais características e vantagens:

  • Captura de Dependências de Longo Alcance: A capacidade de analisar toda a sequência de uma vez permite que os Transformers capturem relações entre palavras distantes umas das outras de forma muito mais eficaz do que as RNNs, que podem “esquecer” informações anteriores em sequências longas.
  • Paralelização: Como o cálculo para cada elemento da sequência não depende estritamente do resultado do elemento anterior (como nas RNNs), grande parte do processamento dentro de um Transformer pode ser feito em paralelo. Isso acelera significativamente o treinamento em hardware moderno (como GPUs e TPUs).
  • Arquitetura Encoder-Decoder: A arquitetura original do Transformer consiste em uma pilha de codificadores (encoders) e uma pilha de decodificadores (decoders). O codificador processa a sequência de entrada (por exemplo, uma frase em português) e cria uma representação rica em contexto. O decodificador usa essa representação e a sequência de saída gerada até o momento (por exemplo, a tradução para inglês) para produzir o próximo elemento da saída. Modelos posteriores, como o BERT, usam apenas a pilha de codificadores, enquanto modelos como o GPT usam apenas a pilha de decodificadores.
  • Multi-Head Attention: Em vez de aplicar a autoatenção uma única vez, os Transformers a aplicam múltiplas vezes em paralelo (as “cabeças” ou heads). Cada “cabeça” pode aprender a focar em diferentes tipos de relações ou aspectos da sequência, tornando o modelo mais robusto.
  • Codificação Posicional (Positional Encoding): Como a autoatenção por si só não considera a ordem das palavras, informações sobre a posição de cada token na sequência são adicionadas às suas representações de entrada para que o modelo saiba a ordem original.

Os Transformers se tornaram a base para muitos dos modelos de linguagem mais avançados (Large Language Models – LLMs) disponíveis hoje, como a família GPT (usada no ChatGPT), BERT, T5, LaMDA, entre outros. Suas aplicações vão muito além da tradução automática inicial, incluindo:

  • Geração de texto (artigos, código, poesia)
  • Sumarização de documentos
  • Respondendo a perguntas (Question Answering)
  • Análise de sentimentos
  • Chatbots e assistentes virtuais

Além do PLN, a arquitetura Transformer foi adaptada com sucesso para outras áreas, como visão computacional (Vision Transformers – ViTs para classificação de imagens e detecção de objetos), processamento de áudio e até mesmo biologia computacional (para análise de sequências genômicas ou estruturas de proteínas).

Esta não é uma lista definitiva de arquiteturas e existem outras, tais como Word2Vec, Doc2vec, Neural Embeddings e variações das arquiteturas aqui apresentadas, como Denoising Autoencoders, Variational Autoencoders, além de outras categorias como Deep Reinforcement Learning. 

Isso conclui a primeira parte deste livro, com uma introdução ao universo do Deep Learning. No próximo capítulo começaremos a ver as redes neurais em ação. Até lá.

Referências:

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Pattern Recognition and Machine Learning

Understanding Activation Functions in Neural Networks

Multilayer Perceptrons

Long Short-Term Memory

Long Short-Term Memory Neural Computation

The Unreasonable Effectiveness of Recurrent Neural Networks

Perceptrons, Expanded Edition

The 8 Neural Network Architectures Machine Learning Researchers Need to Learn

Dynamic Routing Between Capsules

Neural networks and physical systems with emergent collective computational abilities

Deep Boltzmann Machines

Application of Deep Belief Networks for Natural Language Understanding

A fast learning algorithm for deep belief nets

A Beginner’s Guide to Deep Autoencoders

Matrix Capsules With RM Routing

Generative Adversarial Networks (GANs)

Deep Learning Book

Capítulo 9 – A Arquitetura das Redes Neurais

by

No capítulo 11 vamos desenvolver uma rede neural para classificação de dígitos manuscritos, usando linguagem Python (caso ainda não saiba trabalhar com a linguagem, comece agora mesmo com nosso curso online totalmente gratuito Fundamentos de Linguagem Python Para Análise de Dados e Data Science). Mas antes, vamos compreender a terminologia que será muito útil quando estivermos desenvolvendo nosso modelo, estudando a Arquitetura das Redes Neurais. Suponha que tenhamos a rede abaixo:

 

Rede

 

A camada mais à esquerda nesta rede é chamada de camada de entrada e os neurônios dentro da camada são chamados de neurônios de entrada. A camada mais à direita ou a saída contém os neurônios de saída ou, como neste caso, um único neurônio de saída. A camada do meio é chamada de camada oculta, já que os neurônios nessa camada não são entradas ou saídas. O termo “oculto” talvez soe um pouco misterioso – a primeira vez que ouvi o termo, pensei que devesse ter algum significado filosófico ou matemático profundo – mas isso realmente não significa nada mais do que “uma camada que não é entrada ou saída”. A rede acima tem apenas uma única camada oculta, mas algumas redes possuem múltiplas camadas ocultas. Por exemplo, a seguinte rede de quatro camadas tem duas camadas ocultas:

 

Rede

 

Tais redes de camadas múltiplas são chamados de Perceptrons Multicamadas ou MLPs (Multilayer Perceptrons), ou seja, uma rede neural formada por Perceptrons (embora na verdade seja uma rede de neurônios sigmóides, como veremos mais adiante).

O design das camadas de entrada e saída em uma rede geralmente é direto. Por exemplo, suponha que estamos tentando determinar se uma imagem manuscrita representa um “9” ou não. Uma maneira natural de projetar a rede é codificar as intensidades dos pixels da imagem nos neurônios de entrada. Se a imagem for uma imagem em escala de cinza 64 x 64, teríamos 64 × 64 = 4.096  neurônios de entrada, com as intensidades dimensionadas adequadamente entre 0 e 1. A camada de saída conterá apenas um único neurônio com valores inferiores a 0,5 indicando que “a imagem de entrada não é um 9” e valores maiores que 0,5 indicando que “a imagem de entrada é um 9”.

Embora o design das camadas de entrada e saída de uma rede neural seja frequentemente direto, pode haver bastante variação para o design das camadas ocultas. Em particular, não é possível resumir o processo de design das camadas ocultas com poucas regras simples. Em vez disso, pesquisadores de redes neurais desenvolveram muitas heurísticas de design para as camadas ocultas, que ajudam as pessoas a obter o comportamento que querem de suas redes. Conheceremos várias heurísticas de design desse tipo mais adiante ao longo dos próximos capítulos. O design das camadas ocultas é um dos pontos cruciais em modelos de Deep Learning.

Até agora, estamos discutindo redes neurais onde a saída de uma camada é usada como entrada para a próxima camada. Essas redes são chamadas de redes neurais feedforward. Isso significa que não há loops na rede – as informações sempre são alimentadas para a frente, nunca são enviadas de volta. Se tivéssemos loops, acabaríamos com situações em que a entrada para a função σ dependeria da saída. Isso seria difícil de entender e, portanto, não permitimos tais loops.

No entanto, existem outros modelos de redes neurais artificiais em que os circuitos de feedback são possíveis. Esses modelos são chamados de redes neurais recorrentes. A ideia nestes modelos é ter neurônios que disparem por algum período de tempo limitado. Disparar pode estimular outros neurônios, que podem disparar um pouco mais tarde, também por uma duração limitada. Isso faz com que ainda mais neurônios disparem e, ao longo do tempo, conseguimos uma cascata de disparos de neurônios. Loops não causam problemas em tal modelo, uma vez que a saída de um neurônio afeta apenas sua entrada em algum momento posterior, não instantaneamente.

Geralmente, as arquiteturas de redes neurais podem ser colocadas em 3 categorias específicas:

1- Redes Neurais Feed-Forward

Estes são o tipo mais comum de rede neural em aplicações práticas. A primeira camada é a entrada e a última camada é a saída. Se houver mais de uma camada oculta, nós as chamamos de redes neurais “profundas” (ou Deep Learning). Esses tipos de redes neurais calculam uma série de transformações que alteram as semelhanças entre os casos. As atividades dos neurônios em cada camada são uma função não-linear das atividades na camada anterior.

2- Redes Recorrentes

Estes tipos de redes neurais têm ciclos direcionados em seu grafo de conexão. Isso significa que às vezes você pode voltar para onde você começou seguindo as setas. Eles podem ter uma dinâmica complicada e isso pode torná-los muito difíceis de treinar. Entretanto, estes tipos são mais biologicamente realistas.

Atualmente, há muito interesse em encontrar formas eficientes de treinamento de redes recorrentes. As redes neurais recorrentes são uma maneira muito natural de modelar dados sequenciais. Eles são equivalentes a redes muito profundas com uma camada oculta por fatia de tempo; exceto que eles usam os mesmos pesos em cada fatia de tempo e recebem entrada em cada fatia. Eles têm a capacidade de lembrar informações em seu estado oculto por um longo período de tempo, mas é muito difícil treiná-las para usar esse potencial.

3- Redes Conectadas Simetricamente

Estas são como redes recorrentes, mas as conexões entre as unidades são simétricas (elas têm o mesmo peso em ambas as direções). As redes simétricas são muito mais fáceis de analisar do que as redes recorrentes. Elas também são mais restritas no que podem fazer porque obedecem a uma função de energia. As redes conectadas simetricamente sem unidades ocultas são chamadas de “Redes Hopfield”. As redes conectadas simetricamente com unidades ocultas são chamadas de “Máquinas de Boltzmann”.


Dentre estas 3 categorias, podemos listar as arquiteturas principais de redes neurais:

  • Redes Multilayer Perceptron
  • Redes Neurais Convolucionais
  • Redes Neurais Recorrentes
  • Long Short-Term Memory (LSTM)
  • Redes de Hopfield
  • Máquinas de Boltzmann
  • Deep Belief Network
  • Deep Auto-Encoders
  • Generative Adversarial Network
  • Deep Neural Network Capsules 
  • Transformadores

No próximo capítulo, daremos a você uma visão geral sobre cada uma dessas arquiteturas e ao longo dos capítulos seguintes, estudaremos todas elas. Cada umas dessas arquiteturas tem sido usada para resolver diferentes problemas e criar sistemas de Inteligência Artificial. Saber trabalhar com IA de forma eficiente, será determinante para seu futuro profissional.

Referências:

Função Sigmóide

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Pattern Recognition and Machine Learning

Understanding Activation Functions in Neural Networks

Vanishing Gradient Problem

Redes Neurais, princípios e práticas

Neural Networks and Deep Learning (alguns trechos extraídos e traduzidos com autorização do autor Michael Nielsen)

Deep Learning Book

Capítulo 5 – Usando Redes Neurais Para Reconhecer Dígitos Manuscritos

by

O sistema visual humano é uma das maravilhas do mundo. Considere a seguinte sequência de dígitos manuscritos:

Dígitos

A maioria das pessoas reconhece sem esforço esses dígitos como 504192. Essa facilidade é enganosa. Em cada hemisfério do nosso cérebro, os seres humanos têm um córtex visual primário, também conhecido como V1, contendo 140 milhões de neurônios, com dezenas de bilhões de conexões entre eles. E, no entanto, a visão humana envolve não apenas V1, mas uma série inteira de cortices visuais – V2, V3, V4 e V5 – fazendo processamento de imagem progressivamente mais complexo. Nós carregamos em nossas cabeças um supercomputador, sintonizado pela evolução ao longo de centenas de milhões de anos, e soberbamente adaptado para entender o mundo visual. Reconhecer os dígitos manuscritos não é fácil. Em vez disso, nós humanos somos estupendos, surpreendentemente bons, em entender o que nossos olhos nos mostram. Mas quase todo esse trabalho é feito inconscientemente. E, portanto, geralmente não apreciamos o quão difícil é o problema dos nossos sistemas visuais.

A dificuldade de reconhecimento do padrão visual torna-se evidente se você tentar escrever um programa de computador para reconhecer dígitos como os acima. O que parece fácil quando nós seres humanos fazemos, de repente, se torna extremamente difícil. Intuições simples sobre como reconhecemos formas – “um 9 tem um loop no topo e um curso vertical no canto inferior direito” – não é tão simples de se expressar algoritmicamente. Quando você tenta construir essas regras de forma precisa, você se perde rapidamente em diversas exceções, ressalvas e casos especiais. É meio desesperador.

As redes neurais abordam o problema de uma maneira diferente. A ideia é tomar uma grande quantidade de dígitos manuscritos, conhecidos como exemplos de treinamento, e em seguida, desenvolver um sistema que possa aprender com esses exemplos de treinamento. Em outras palavras, a rede neural usa os exemplos para inferir automaticamente regras para o reconhecimento de dígitos manuscritos. Além disso, ao aumentar o número de exemplos de treinamento, a rede pode aprender mais sobre a caligrafia, e assim melhorar sua precisão. Podemos construir um reconhecedor de dígitos manuscritos melhor usando milhares, milhões ou bilhões de exemplos de treinamento.

MNIST

Ao longo dos próximos capítulos começaremos nossa jornada rumo às arquiteturas mais avançadas de Deep Learning, desenvolvendo um programa de computador implementando uma rede neural que aprende a reconhecer os dígitos manuscritos. O programa não usará bibliotecas de redes neurais especiais (usaremos apenas linguagem Python). Mas este programa pode reconhecer dígitos com uma precisão de mais de 96%, sem intervenção humana. Além disso, em capítulos posteriores, desenvolveremos ideias que podem melhorar a precisão para mais de 99%. Na verdade, as melhores redes neurais comerciais são agora tão boas que são usadas pelos bancos para processar cheques e por agências de correio para reconhecer endereços.

Estamos nos concentrando no reconhecimento de manuscrito porque é um excelente problema protótipo para aprender sobre redes neurais em geral. Como um protótipo, ele atinge um ponto interessante: é desafiador – não é tão simples reconhecer os dígitos manuscritos – mas também não é tão difícil e nem requer uma solução extremamente complicada, ou um tremendo poder computacional. Além disso, é uma ótima maneira de desenvolver técnicas mais avançadas, como a aprendizagem profunda. E assim, ao longo do livro, retornaremos repetidamente ao problema do reconhecimento de dígitos manuscritos. Mais tarde, no livro, vamos discutir como essas ideias podem ser aplicadas a outros problemas em visão computacional, e também em reconhecimento da fala, processamento de linguagem natural e outras áreas.

Ao longo do caminho, desenvolveremos muitas ideias-chave sobre as redes neurais, incluindo dois tipos importantes de neurônios artificiais (o perceptron e o neurônio sigmóide) e o algoritmo de aprendizagem padrão para redes neurais, conhecido como descida estocástica do gradiente. Explicaremos porque as coisas são feitas da maneira que elas são e na construção de sua intuição de redes neurais. Isso requer uma discussão mais longa do que apenas apresentar a mecânica básica do que está acontecendo, mas vale a pena para o entendimento mais profundo que você alcançará. E ao final deste livro, você terá uma boa compreensão do que é aprendizado profundo e como isso está transformando o mundo!

Caso você não tenha conhecimento em linguagem Python, recomendamos o curso gratuito Fundamentos de Linguagem Python Para Análise de Dados e Data Science. Ele vai fornecer uma ótima base de tudo que você precisa para começar a desenvolver suas redes neurais.

Referências:

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Pattern Recognition and Machine Learning

Redes Neurais, princípios e práticas

Neural Networks and Deep Learning (alguns trechos extraídos e traduzidos com autorização do autor Michael Nielsen)

Deep Learning Book

Capítulo 3 – O Que São Redes Neurais Artificiais Profundas ou Deep Learning?

by

Aprendizagem Profunda ou Deep Learning, é uma sub-área da Aprendizagem de Máquina, que emprega algoritmos para processar dados e imitar o processamento feito pelo cérebro humano. Mas O Que São Redes Neurais Artificiais Profundas ou Deep Learning? É o que veremos neste capítulo. Não se preocupe se alguns termos mais técnicos não fizerem sentido agora. Todos eles serão estudados ao longo deste livro online.

Deep Learning  usa camadas de neurônios matemáticos para processar dados, compreender a fala humana e reconhecer objetos visualmente. A informação é passada através de cada camada, com a saída da camada anterior fornecendo entrada para a próxima camada. A primeira camada em uma rede é chamada de camada de entrada, enquanto a última é chamada de camada de saída. Todas as camadas entre as duas são referidas como camadas ocultas. Cada camada é tipicamente um algoritmo simples e uniforme contendo um tipo de função de ativação.

 

Neural Network

Fig4 – Rede Neural Simples e Rede Neural Profunda (Deep Learning)

 

A aprendizagem profunda é responsável por avanços recentes em visão computacional, reconhecimento de fala, processamento de linguagem natural e reconhecimento de áudio. O aprendizado profundo é baseado no conceito de redes neurais artificiais, ou sistemas computacionais que imitam a maneira como o cérebro humano funciona.

A extração de recursos é outro aspecto da Aprendizagem Profunda. A extração de recursos usa um algoritmo para construir automaticamente “recursos” significativos dos dados para fins de treinamento, aprendizado e compreensão. Normalmente, o Cientista de Dados, ou Engenheiro de IA, é responsável pela extração de recursos.

O aumento rápido e o aparente domínio do aprendizado profundo sobre os métodos tradicionais de aprendizagem de máquina em uma variedade de tarefas tem sido surpreendente de testemunhar e, às vezes, difícil de explicar. Deep Learning é uma evolução das Redes Neurais, que por sua vez possuem uma história fascinante que remonta à década de 1940, cheia de altos e baixos, voltas e reviravoltas, amigos e rivais, sucessos e fracassos. Em uma história digna de um filme dos anos 90, uma ideia que já foi uma espécie de patinho feio floresceu para se tornar a bola da vez.

Consequentemente, o interesse em aprendizagem profunda tem disparado, com cobertura constante na mídia popular. A pesquisa de aprendizagem profunda agora aparece rotineiramente em revistas como Science, Nature, Nature Methods e Forbes apenas para citar alguns. O aprendizado profundo conquistou Go, aprendeu a dirigir um carro, diagnosticou câncer de pele e autismo, tornou-se um falsificador de arte mestre e pode até alucinar imagens fotorrealistas.

Os primeiros algoritmos de aprendizagem profunda que possuíam múltiplas camadas de características não-lineares podem ser rastreados até Alexey Grigoryevich Ivakhnenko (desenvolveu o Método do Grupo de Manipulação de Dados) e Valentin Grigor’evich Lapa (autor de Cybernetics and Forecasting Techniques) em 1965 (Figura 5), que usaram modelos finos mas profundos com funções de ativação polinomial os quais eles analisaram com métodos estatísticos. Em cada camada, eles selecionavam os melhores recursos através de métodos estatísticos e encaminhavam para a próxima camada. Eles não usaram Backpropagation para treinar a rede de ponta a ponta, mas utilizaram mínimos quadrados camada-por-camada, onde as camadas anteriores foram independentemente instaladas em camadas posteriores (um processo lento e manual).

GMDH-network

Fig5 – Arquitetura da primeira rede profunda conhecida treinada por Alexey Grigorevich Ivakhnenko em 1965.

 

No final da década de 1970, o primeiro inverno de AI começou, resultado de promessas que não poderiam ser mantidas. O impacto desta falta de financiamento limitou a pesquisa em Redes Neurais Profundas e Inteligência Artificial. Felizmente, houve indivíduos que realizaram a pesquisa sem financiamento.

As primeiras “redes neurais convolutivas” foram usadas por Kunihiko Fukushima. Fukushima concebeu redes neurais com múltiplas camadas de agrupamento e convoluções. Em 1979, ele desenvolveu uma rede neural artificial, chamada Neocognitron, que usava um design hierárquico e multicamadas. Este design permitiu ao computador “aprender” a reconhecer padrões visuais. As redes se assemelhavam a versões modernas, mas foram treinadas com uma estratégia de reforço de ativação recorrente em múltiplas camadas, que ganhou força ao longo do tempo. Além disso, o design de Fukushima permitiu que os recursos importantes fossem ajustados manualmente aumentando o “peso” de certas conexões.

Muitos dos conceitos de Neocognitron continuam a ser utilizados. O uso de conexões de cima para baixo e novos métodos de aprendizagem permitiram a realização de uma variedade de redes neurais. Quando mais de um padrão é apresentado ao mesmo tempo, o Modelo de Atenção Seletiva pode separar e reconhecer padrões individuais deslocando sua atenção de um para o outro (o mesmo processo que usamos em multitarefa). Um Neocognitron moderno não só pode identificar padrões com informações faltantes (por exemplo, um número 5 desenhado de maneira incompleta), mas também pode completar a imagem adicionando as informações que faltam. Isso pode ser descrito como “inferência”.

O Backpropagation, o uso de erros no treinamento de modelos de Deep Learning, evoluiu significativamente em 1970. Foi quando Seppo Linnainmaa escreveu sua tese de mestrado, incluindo um código FORTRAN para Backpropagation. Infelizmente, o conceito não foi aplicado às redes neurais até 1985. Foi quando Rumelhart, Williams e Hinton demonstraram o Backpropagation em uma rede neural que poderia fornecer representações de distribuição “interessantes”. Filosoficamente, essa descoberta trouxe à luz a questão dentro da psicologia cognitiva de saber se a compreensão humana depende da lógica simbólica (computacionalismo) ou de representações distribuídas (conexão). Em 1989, Yann LeCun forneceu a primeira demonstração prática de Backpropagation no Bell Labs. Ele combinou redes neurais convolutivas com Backpropagation para ler os dígitos “manuscritos” (assunto do próximo capítulo). Este sistema foi usado para ler o número de cheques manuscritos.

Deep Learning

Fig6 – Os pioneiros da Inteligência Artificial. Da esquerda para a direita: Yann LeCun, Geoffrey Hinton, Yoshua Bengio e Andrew Ng

Porém, tivemos neste período o que ficou conhecido como segundo Inverno da IA, que ocorreu entre 1985-1990, que também afetou pesquisas em Redes Neurais e Aprendizagem Profunda. Vários indivíduos excessivamente otimistas haviam exagerado o potencial “imediato” da Inteligência Artificial, quebrando as expectativas e irritando os investidores. A raiva era tão intensa, que a frase Inteligência Artificial atingiu o status de pseudociência. Felizmente, algumas pessoas continuaram trabalhando em IA e Deep Learning, e alguns avanços significativos foram feitos. Em 1995, Dana Cortes e Vladimir Vapnik desenvolveram a máquina de vetor de suporte ou Support Vector Machine (um sistema para mapear e reconhecer dados semelhantes). O LSTM (Long-Short Term Memory) para redes neurais recorrentes foi desenvolvido em 1997, por Sepp Hochreiter e Juergen Schmidhuber.

O próximo passo evolutivo significativo para Deep Learning ocorreu em 1999, quando os computadores começaram a se tornar mais rápidos no processamento de dados e GPUs (unidades de processamento de gráfico) foram desenvolvidas. O uso de GPUs significou um salto no tempo de processamento, resultando em um aumento das velocidades computacionais em 1000 vezes ao longo de um período de 10 anos. Durante esse período, as redes neurais começaram a competir com máquinas de vetor de suporte. Enquanto uma rede neural poderia ser lenta em comparação com uma máquina de vetor de suporte, as redes neurais ofereciam melhores resultados usando os mesmos dados. As redes neurais também têm a vantagem de continuar a melhorar à medida que mais dados de treinamento são adicionados.

Em torno do ano 2000, apareceu o problema conhecido como Vanishing Gradient. Foi descoberto que as “características” aprendidas em camadas mais baixas não eram aprendidas pelas camadas superiores, pois nenhum sinal de aprendizado alcançou essas camadas. Este não era um problema fundamental para todas as redes neurais, apenas aquelas com métodos de aprendizagem baseados em gradientes. A origem do problema acabou por ser certas funções de ativação. Uma série de funções de ativação condensavam sua entrada, reduzindo, por sua vez, a faixa de saída de forma um tanto caótica. Isso produziu grandes áreas de entrada mapeadas em uma faixa extremamente pequena. Nessas áreas de entrada, uma grande mudança será reduzida a uma pequena mudança na saída, resultando em um gradiente em queda. Duas soluções utilizadas para resolver este problema foram o pré-treino camada-a-camada e o desenvolvimento de uma memória longa e de curto prazo.

Em 2001, um relatório de pesquisa do Grupo META (agora chamado Gartner) descreveu os desafios e oportunidades no crescimento do volume de dados. O relatório descreveu o aumento do volume de dados e a crescente velocidade de dados como o aumento da gama de fontes e tipos de dados. Este foi um apelo para se preparar para a investida do Big Data, que estava apenas começando.

Em 2009, Fei-Fei Li, professora de IA em Stanford na Califórnia, lançou o ImageNet e montou uma base de dados gratuita de mais de 14 milhões de imagens etiquetadas. Eram necessárias imagens marcadas para “treinar” as redes neurais. A professora Li disse: “Nossa visão é que o Big Data mudará a maneira como a aprendizagem de máquina funciona. Data drives learning.”. Ela acertou em cheio!

Até 2011, a velocidade das GPUs aumentou significativamente, possibilitando a formação de redes neurais convolutivas “sem” o pré-treino camada por camada. Com o aumento da velocidade de computação, tornou-se óbvio que Deep Learning tinha vantagens significativas em termos de eficiência e velocidade. Um exemplo é a AlexNet, uma rede neural convolutiva, cuja arquitetura ganhou várias competições internacionais durante 2011 e 2012. As unidades lineares retificadas foram usadas para melhorar a velocidade.

Também em 2012, o Google Brain lançou os resultados de um projeto incomum conhecido como The Cat Experiment. O projeto de espírito livre explorou as dificuldades de “aprendizagem sem supervisão”. A Aprendizagem profunda usa “aprendizagem supervisionada”, o que significa que a rede neural convolutiva é treinada usando dados rotulados. Usando a aprendizagem sem supervisão, uma rede neural convolucional é alimentada com dados não marcados, e é então solicitada a busca de padrões recorrentes.

O Cat Experiment usou uma rede neural distribuída por mais de 1.000 computadores. Dez milhões de imagens “sem etiqueta” foram tiradas aleatoriamente do YouTube, mostradas ao sistema e, em seguida, o software de treinamento foi autorizado a ser executado. No final do treinamento, um neurônio na camada mais alta foi encontrado para responder fortemente às imagens de gatos. Andrew Ng, o fundador do projeto, disse: “Nós também encontramos um neurônio que respondeu fortemente aos rostos humanos”. A aprendizagem não supervisionada continua a ser um um campo ativo de pesquisa em Aprendizagem Profunda.

Atualmente, o processamento de Big Data e a evolução da Inteligência Artificial são ambos dependentes da Aprendizagem Profunda. Com Deep Learning podemos construir sistemas inteligentes e estamos nos aproximando da criação de uma IA totalmente autônoma. Isso vai gerar impacto em todas os segmentos da sociedade e aqueles que souberem trabalhar com a tecnologia, serão os líderes desse novo mundo que se apresenta diante de nós.

No próximo capítulo você vai começar a compreender tecnicamente como funciona a Aprendizagem Profunda. Até o capítulo 4.

Referências:

Deep Learning Para Aplicações de Inteligência Artificial com Python e C++

Deep Learning in a Nutshell: History and Training from NVIDIA

Linnainmaa, S. (1970). The representation of the cumulative rounding error of an algorithm as a Taylor expansion of the local rounding errors. Master’s thesis, Univ. Helsinki.

P. Werbos. Beyond Regression: New Tools for Prediction and Analysis in the Behavioral Sciences. PhD thesis, Harvard University, Cambridge, MA, 1974.

Werbos, P.J. (2006). Backwards differentiation in AD and neural nets: Past links and new opportunities. In Automatic Differentiation: Applications, Theory, and Implementations, pages 15-34. Springer.

Rumelhart, D. E., Hinton, G. E., and Williams, R. J. (1986). Learning representations by back-propagating errors. Nature, 323, 533–536.

Widrow, B., & Lehr, M. (1990). 30 years of adaptive neural networks: perceptron, madaline, and backpropagation. Proceedings of the IEEE, 78(9), 1415-1442.

D. E. Rumelhart, G. E. Hinton, and R. J. Williams. 1986. Learning internal representations by error propagation. In Parallel distributed processing: explorations in the microstructure of cognition, vol. 1, David E. Rumelhart, James L. McClelland, and CORPORATE PDP Research Group (Eds.). MIT Press, Cambridge, MA, USA 318-362

Deep Learning Book

Capítulo 2 – Uma Breve História das Redes Neurais Artificiais

by

Para compreender onde estamos hoje, precisamos olhar para o passado e analisar como chegamos até aqui. Vejamos então Uma Breve História das Redes Neurais Artificiais.

O cérebro humano é uma máquina altamente poderosa e complexa capaz de processar uma grande quantidade de informações em tempo mínimo. As unidades principais do cérebro são os neurônios e é por meio deles que as informações são transmitidas e processadas. As tarefas realizadas pelo cérebro intrigam os pesquisadores, como por exemplo, a capacidade do cérebro de reconhecer um rosto familiar dentre uma multidão em apenas milésimos de segundo. As respostas sobre alguns enigmas do funcionamento do cérebro ainda não foram respondidas e se perpetuam ate os dias de hoje. O que é conhecido sobre o funcionamento do cérebro é que o mesmo desenvolve suas regras através da experiência adquirida em situações vividas anteriormente.

Cérebro Humano

Fig1 – Cérebro humano, a máquina mais fantástica que existe no Planeta Terra.

O desenvolvimento do cérebro humano ocorre principalmente nos dois primeiros anos de vida, mas se arrasta por toda a vida. Inspirando-se neste modelo, diversos pesquisadores tentaram simular o funcionamento do cérebro, principalmente o processo de aprendizagem por experiência, a fim de criar sistemas inteligentes capazes de realizar tarefas como classificação, reconhecimento de padrões, processamento de imagens, entre outras atividades. Como resultado destas pesquisas surgiu o modelo do neurônio artificial e posteriormente um sistema com vários neurônios interconectados, a chamada Rede Neural.

Em 1943, o neurofisiologista Warren McCulloch e o matemático Walter Pitts escreveram um artigo sobre como os neurônios poderiam funcionar e para isso, eles modelaram uma rede neural simples usando circuitos elétricos.

Warren McCulloch e Walter Pitts criaram um modelo computacional para redes neurais baseadas em matemática e algoritmos denominados lógica de limiar (threshold logic). Este modelo abriu o caminho para a pesquisa da rede neural dividida em duas abordagens: uma abordagem focada em processos biológicos no cérebro, enquanto a outra focada na aplicação de redes neurais à inteligência artificial.

Em 1949, Donald Hebb escreveu The Organization of Behavior, uma obra que apontou o fato de que os caminhos neurais são fortalecidos cada vez que são usados, um conceito fundamentalmente essencial para a maneira como os humanos aprendem. Se dois nervos dispararem ao mesmo tempo, argumentou, a conexão entre eles é melhorada.

À medida que os computadores se tornaram mais avançados na década de 1950, finalmente foi possível simular uma hipotética rede neural. O primeiro passo para isso foi feito por Nathanial Rochester dos laboratórios de pesquisa da IBM. Infelizmente para ele, a primeira tentativa de fazê-lo falhou.

No entanto, ao longo deste tempo, os defensores das “máquinas pensantes” continuaram a argumentar suas pesquisas. Em 1956, o Projeto de Pesquisa de Verão de Dartmouth sobre Inteligência Artificial proporcionou um impulso tanto à Inteligência Artificial como às Redes Neurais. Um dos resultados deste processo foi estimular a pesquisa em IA na parte de processamento neural.

Nos anos seguintes ao Projeto Dartmouth, John von Neumann sugeriu imitar funções simples de neurônios usando relés telegráficos ou tubos de vácuo. Além disso, Frank Rosenblatt, um neurobiologista, começou a trabalhar no Perceptron. Ele estava intrigado com o funcionamento do olho de uma mosca. Grande parte do processamento feito por uma mosca ao decidir fugir, é feito em seus olhos. O Perceptron, que resultou dessa pesquisa, foi construído em hardware e é a mais antiga rede neural ainda em uso hoje. Um Percetron de camada única foi útil para classificar um conjunto de entradas de valor contínuo em uma de duas classes. O Perceptron calcula uma soma ponderada das entradas, subtrai um limite e passa um dos dois valores possíveis como resultado. Infelizmente, o Perceptron é limitado e foi comprovado como tal durante os “anos desiludidos” por Marvin Minsky e o livro de Seymour Papert de 1969, Perceptrons.

Deep Learning Zoo

Fig2 – Algumas Arquiteturas de Redes Neurais. Fonte: Deep Learning Zoo

Em 1959, Bernard Widrow e Marcian Hoff, de Stanford, desenvolveram modelos denominados “ADALINE” e “MADALINE”. Em uma exibição típica do amor de Stanford por siglas, os nomes provêm do uso de múltiplos elementos ADAptive LINear. ADALINE foi desenvolvido para reconhecer padrões binários de modo que, se ele estivesse lendo bits de transmissão de uma linha telefônica, poderia prever o próximo bit. MADALINE foi a primeira rede neural aplicada a um problema do mundo real, usando um filtro adaptativo que elimina ecos nas linhas telefônicas. Embora o sistema seja tão antigo como os sistemas de controle de tráfego aéreo, ele ainda está em uso comercial.

Infelizmente, esses sucessos anteriores levaram as pessoas a exagerar o potencial das redes neurais, particularmente à luz da limitação na eletrônica, então disponível na época. Este exagero excessivo, que decorreu do mundo acadêmico e técnico, infectou a literatura geral da época. Muitas promessas foram feitas, mas o resultado foi o desapontamento. Além disso, muitos escritores começaram a refletir sobre o efeito que teria “máquinas pensantes” no homem. A série de Asimov em robôs revelou os efeitos sobre a moral e os valores do homem quando máquinas fossem capazes de fazer todo o trabalho da humanidade. Outros escritores criaram computadores mais sinistros, como HAL do filme 2001.

Toda essa discussão sobre o efeito da Inteligência Artificial sobre a vida humana, aliada aos poucos progressos, fizeram vozes respeitadas criticar a pesquisa em redes neurais. O resultado foi a redução drástica de grande parte do financiamento em pesquisas. Esse período de crescimento atrofiado durou até 1981, sendo conhecido como o Inverno da IA (AI Winter).

Em 1982, vários eventos provocaram um renovado interesse. John Hopfield da Caltech apresentou um documento à Academia Nacional de Ciências. A abordagem de Hopfield não era simplesmente modelar cérebros, mas criar dispositivos úteis. Com clareza e análise matemática, ele mostrou como essas redes poderiam funcionar e o que poderiam fazer. No entanto, o maior recurso de Hopfield foi seu carisma. Ele era articulado e simpático e isso colaborou bastante para que ele fosse ouvido.

Em 1985, o Instituto Americano de Física começou o que se tornou uma reunião anual – Redes Neurais para Computação. Em 1987, a primeira Conferência Internacional sobre Redes Neurais do Institute of Electrical and Electronic Engineer’s (IEEE) atraiu mais de 1.800 participantes.

Em 1986, com redes neurais de várias camadas nas notícias, o problema era como estender a regra Widrow-Hoff para várias camadas. Três grupos independentes de pesquisadores, dentre os quais David Rumelhart, ex-membro do departamento de psicologia de Stanford, apresentaram ideias semelhantes que agora são chamadas de redes Backpropagation porque distribuem erros de reconhecimento de padrões em toda a rede. As redes híbridas utilizavam apenas duas camadas, essas redes de Backpropagation utilizam muitas. O resultado é que as redes de Backpropagation “aprendem” de forma mais lenta, pois necessitam, possivelmente, de milhares de iterações para aprender, mas geram um resultado muito preciso.

Agora, as redes neurais são usadas em várias aplicações. A ideia fundamental por trás da natureza das redes neurais é que, se ela funcionar na natureza, deve ser capaz de funcionar em computadores. O futuro das redes neurais, no entanto, reside no desenvolvimento de hardware. As redes neurais rápidas e eficientes dependem do hardware especificado para seu eventual uso.

O diagrama abaixo mostra alguns marcos importantes na evolução e pesquisa das redes neurais artificiais. O fato, é que ainda estamos escrevendo esta história e muita evolução está ocorrendo neste momento, através do trabalho de milhares de pesquisadores e profissionais de Inteligência Artificial em todo mundo. E você, não quer ajudar a escrever esta história?

Timeline das Redes Neurais

Fig3 – Marcos no desenvolvimento das redes neurais.

Podemos resumir assim os principais marcos na pesquisa e evolução das redes neurais artificiais até chegarmos ao Deep Learning:

1943: Warren McCulloch e Walter Pitts criam um modelo computacional para redes neurais baseadas em matemática e algoritmos denominados lógica de limiar.

1958: Frank Rosenblatt cria o Perceptron, um algoritmo para o reconhecimento de padrões baseado em uma rede neural computacional de duas camadas usando simples adição e subtração. Ele também propôs camadas adicionais com notações matemáticas, mas isso não seria realizado até 1975.

1980: Kunihiko Fukushima propõe a Neoconitron, uma rede neural de hierarquia, multicamada, que foi utilizada para o reconhecimento de caligrafia e outros problemas de reconhecimento de padrões.

1989: os cientistas conseguiram criar algoritmos que usavam redes neurais profundas, mas os tempos de treinamento para os sistemas foram medidos em dias, tornando-os impraticáveis ​​para o uso no mundo real.

1992: Juyang Weng publica o Cresceptron, um método para realizar o reconhecimento de objetos 3-D automaticamente a partir de cenas desordenadas.

Meados dos anos 2000: o termo “aprendizagem profunda” começa a ganhar popularidade após um artigo de Geoffrey Hinton e Ruslan Salakhutdinov mostrar como uma rede neural de várias camadas poderia ser pré-treinada uma camada por vez.

2009: acontece o NIPS Workshop sobre Aprendizagem Profunda para Reconhecimento de Voz e descobre-se que com um conjunto de dados suficientemente grande, as redes neurais não precisam de pré-treinamento e as taxas de erro caem significativamente.

2012: algoritmos de reconhecimento de padrões artificiais alcançam desempenho em nível humano em determinadas tarefas. E o algoritmo de aprendizagem profunda do Google é capaz de identificar gatos.

2014: o Google compra a Startup de Inteligência Artificial chamada DeepMind, do Reino Unido, por £ 400m

2015: Facebook coloca a tecnologia de aprendizado profundo – chamada DeepFace – em operação para marcar e identificar automaticamente usuários do Facebook em fotografias. Algoritmos executam tarefas superiores de reconhecimento facial usando redes profundas que levam em conta 120 milhões de parâmetros.

2016: o algoritmo do Google DeepMind, AlphaGo, mapeia a arte do complexo jogo de tabuleiro Go e vence o campeão mundial de Go, Lee Sedol, em um torneio altamente divulgado em Seul.

2017: adoção em massa do Deep Learning em diversas aplicações corporativas e mobile, além do avanço em pesquisas. Todos os eventos de tecnologia ligados a Data Science, IA e Big Data, apontam Deep Learning como a principal tecnologia para criação de sistemas inteligentes.

2022: lançamento do ChatGPT, interface web para um LLM (Large Language Model) e a explosão no uso de IA em todo planeta. LLMs são arquiteturas de Deep Learning baseadas em Transformadores e módulo de auto-atenção (como veremos mais a frente).

2025: ano dos Agentes de IA, softwares autônomos baseados em IA, capazes de realizar tarefas em nível humano.

A promessa do aprendizado profundo não é que os computadores comecem a pensar como seres humanos. Isso é como pedir uma maçã para se tornar uma laranja. Em vez disso, demonstra que, dado um conjunto de dados suficientemente grande, processadores rápidos e um algoritmo suficientemente sofisticado, os computadores podem começar a realizar tarefas que até então só podiam ser realizadas apenas por seres humanos, como reconhecer imagens e voz, criar obras de arte ou tomar decisões por si mesmo.

Os estudos sobre as redes neurais sofreram uma grande revolução a partir dos anos 80 e esta área de estudos tem se destacado, seja pelas promissoras características apresentadas pelos modelos de redes neurais propostos, seja pelas condições tecnológicas atuais de implementação que permitem desenvolver arrojadas implementações de arquiteturas neurais paralelas em hardwares dedicado, obtendo assim ótimas performances destes sistemas (bastante superiores aos sistemas convencionais). A evolução natural das redes neurais, são as redes neurais profundas (ou Deep Learning). Mas isso é o que vamos discutir no próximo capítulo! Até lá.

Referências:

Christopher D. Manning. (2015). Computational Linguistics and Deep Learning Computational Linguistics, 41(4), 701–707.

F. Rosenblatt. The perceptron, a perceiving and recognizing automaton Project Para. Cornell Aeronautical Laboratory, 1957.

W. S. McCulloch and W. Pitts. A logical calculus of the ideas immanent in nervous activity. The bulletin of mathematical biophysics, 5(4):115–133, 1943.

The organization of behavior: A neuropsychological theory. D. O. Hebb. John Wiley And Sons, Inc., New York, 1949

B. Widrow et al. Adaptive ”Adaline” neuron using chemical ”memistors”. Number Technical Report 1553-2. Stanford Electron. Labs., Stanford, CA, October 1960.

“New Navy Device Learns By Doing”, New York Times, July 8, 1958.

Perceptrons. An Introduction to Computational Geometry. MARVIN MINSKY and SEYMOUR PAPERT. M.I.T. Press, Cambridge, Mass., 1969.

Minsky, M. (1952). A neural-analogue calculator based upon a probability model of reinforcement. Harvard University Pychological Laboratories internal report.

Deep Learning Book

Capítulo 65 – Distribuições de Probabilidade, Redes Neurais e Reinforcement Learning

by

Nos capítulos anteriores estudamos os conceitos gerais ligados ao Aprendizado Por Reforço (Reinforcement Learning). A partir de agora vamos entrar nos detalhes mais técnicos ligados a este importante método de aprendizagem de máquina, estudando Distribuições de Probabilidade, Redes Neurais e Reinforcement Learning. Acompanhe.

O Objetivo do Aprendizado Por Reforço

O objetivo do Aprendizado Por Reforço é escolher a melhor ação para qualquer estado, o que significa que as ações devem ser classificadas e valores devem ser atribuídos em relação uma a outra. Como essas ações dependem do estado, o que realmente estamos medindo é o valor dos pares de ação e estado; ou seja, uma ação tomada de um determinado estado, algo que o agente fez em algum lugar. Aqui estão alguns exemplos para demonstrar que o valor e o significado de uma ação dependem do estado em que é tomada:

  • Se a ação é se casar com alguém, casar com uma pessoa de 35 anos quando você tem 18 anos provavelmente significa algo diferente de casar com uma pessoa de 35 anos quando você tem 90 anos, e esses dois resultados provavelmente têm motivações diferentes e levam a diferentes resultados.
  • Se a ação estiver gritando “Fogo!”, Então executar a ação em um teatro lotado deve significar algo diferente de executar a ação ao lado de um esquadrão de homens armados com metralhadoras. Não podemos prever o resultado de uma ação sem conhecer o contexto.

Mapeamos os pares estado-ação para os valores que esperamos que eles produzam com a função Q, descrita no capítulo anterior. A função Q usa como entrada o estado e a ação de um agente e os mapeia para prováveis ​​recompensas.

O Aprendizado Por Reforço é o processo de executar o agente por meio de sequências de pares de ação e estado, observando as recompensas resultantes e adaptando as previsões da função Q àquelas recompensas até que ele preveja com precisão o melhor caminho a ser seguido pelo agente. Essa previsão é conhecida como uma política.

Distribuição de Probabilidade

O Aprendizado Por Reforço é uma tentativa de modelar uma distribuição de probabilidade complexa de recompensas em relação a um número muito grande de pares de ação de estado. Esse é um dos motivos pelos quais o Aprendizado Por Reforço é combinado com, digamos, um processo de decisão de Markov, um método de amostragem de uma distribuição complexa para inferir suas propriedades. Assemelha-se muito ao problema que inspirou Stan Ulam a inventar o método de Monte Carlo; ou seja, tentar inferir as chances de que uma determinada “mão” em um jogo de carta seja bem-sucedida.

Qualquer abordagem estatística é essencialmente uma confissão de ignorância. A imensa complexidade de alguns fenômenos (biológicos, políticos, sociológicos ou relacionados a jogos de tabuleiro) torna impossível raciocinar a partir de alguns princípios. A única maneira de estudá-los é através da estatística, medindo eventos superficiais e tentando estabelecer correlações entre eles, mesmo quando não entendemos o mecanismo pelo qual eles se relacionam. O Aprendizado Por Reforço, como redes neurais profundas, é uma dessas estratégias, contando com a amostragem para extrair informações dos dados.

Depois de um pouco de tempo empregando algo como um processo de decisão de Markov para aproximar a distribuição de probabilidade da recompensa sobre pares de ação do estado, um algoritmo de Aprendizado Por Reforço pode tender a repetir ações que levam à recompensa e deixar de testar alternativas. Há uma tensão entre a exploração de recompensas conhecidas e a exploração contínua para descobrir novas ações que também levam à vitória. Assim como as empresas de petróleo têm a dupla função de extrair petróleo de campos conhecidos e perfurar novas reservas, também podem ser criados algoritmos de Aprendizado Por Reforço para explorar em graus variados, a fim de garantir que eles não tomem ações recompensadoras em detrimento de vencedores conhecidos.

O Aprendizado Por Reforço é iterativo. Em suas aplicações mais interessantes, não começa sabendo quais recompensas os pares de ação e estado produzirão. Ele aprende essas relações percorrendo estados repetidas vezes, como atletas ou músicos percorrem estados na tentativa de melhorar seu desempenho.

Redes Neurais

E onde as redes neurais se encaixam?

As redes neurais são aproximadores de função, que são particularmente úteis no Aprendizado Por Reforço quando o espaço de estado ou espaço de ação é muito grande para ser completamente conhecido.

Uma rede neural pode ser usada para aproximar uma função de valor ou uma função de política. Ou seja, as redes neurais podem aprender a mapear estados para valores ou pares de ação e estado para valores Q. Em vez de usar uma tabela de pesquisa para armazenar, indexar e atualizar todos os estados possíveis e seus valores, o que é impossível com problemas muito grandes, podemos treinar uma rede neural em amostras do estado ou espaço de ação para aprender a prever o quanto esses valores são importantes, nosso objetivo no Aprendizado Por Reforço.

As redes neurais usam coeficientes para aproximar a função que relaciona insumos (entradas) a produtos (saídas), e seu aprendizado consiste em encontrar os coeficientes ou pesos certos, ajustando iterativamente esses pesos ao longo de gradientes que prometem menos erros. No Aprendizado Por Reforço, redes convolucionais podem ser usadas para reconhecer o estado de um agente quando a entrada é visual; por exemplo. a tela em que o agente está em um jogo, ou o terreno percorrido por um drone. Ou seja, eles realizam sua tarefa típica de reconhecimento de imagem.

Mas as redes convolucionais derivam interpretações diferentes das imagens no Aprendizado Por Reforço do que no Aprendizado Supervisionado. No Aprendizado Supervisionado, a rede aplica um rótulo a uma imagem, como no exemplo abaixo:

conv_classifier

De fato, a rede classificará os rótulos que melhor se ajustam à imagem em termos de probabilidades. Na imagem de um gato, pode-se decidir que a imagem tem 80% de probabilidade de ser um gato, 50% de ser um cavalo e 30% de ser um cachorro.

No Aprendizado Por Reforço, dada uma imagem que representa um estado, uma rede convolucional pode classificar as ações possíveis de executar nesse estado; por exemplo, pode prever que correr à direita retornará 5 pontos, pular 7 e correr à esquerda nenhum.

conv_agent

A imagem acima ilustra o que um agente faz, mapeando um estado para a melhor ação.

Reinforcement Learning

Uma política mapeia um estado para uma ação.

Se você se lembra, isso é diferente de Q, que mapeia pares de ações de estado para recompensas.

Para ser mais específico, Q mapeia pares de ação de estado para a combinação mais alta de recompensa imediata com todas as recompensas futuras que podem ser obtidas por ações posteriores na trajetória. Aqui está a equação para Q:

q_learning_equation

Depois de atribuir valores às recompensas esperadas, a função Q simplesmente seleciona o par de ação de estado com o maior valor chamado Q.

No início do Aprendizado Por Reforço, os coeficientes da rede neural podem ser inicializados estocástica ou aleatoriamente. Usando o feedback do ambiente, a rede neural pode usar a diferença entre sua recompensa esperada e a recompensa verdadeira para ajustar seus pesos e melhorar sua interpretação dos pares de ação do estado.

Esse ciclo de feedback é análogo à retropropagação de erro no Aprendizado Supervisionado. No entanto, o Aprendizado Supervisionado começa com o conhecimento dos rótulos verdadeiros que a rede neural está tentando prever. Seu objetivo é criar um modelo que mapeie imagens diferentes para seus respectivos nomes.

O Aprendizado Por Reforço depende do ambiente para enviar a ele um número escalar em resposta a cada nova ação. As recompensas retornadas pelo ambiente podem ser variadas, atrasadas ou afetadas por variáveis ​​desconhecidas, introduzindo ruído no loop de feedback. Isso nos leva a uma expressão mais completa da função Q, que leva em consideração não apenas as recompensas imediatas produzidas por uma ação, mas também as recompensas atrasadas que podem ser retornadas várias vezes mais fundo na sequência.

Como seres humanos, a função Q é recursiva. Chamar a função Q em um determinado par de estado-ação exige que chamemos uma função Q aninhada para prever o valor do próximo estado, que por sua vez depende da função Q do estado seguinte e assim por diante.

Continue acompanhando os próximos capítulos.

Referências:

Inteligência Artificial Aplicada a Finanças

Customizando Redes Neurais com Funções de Ativação Alternativas

A Beginner’s Guide to Deep Reinforcement Learning

What is reinforcement learning? The complete guide

Reinforcement learning

Applications of Reinforcement Learning in Real World

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Recurrent neural network based language model

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 59 – Principais Tipos de Redes Neurais Artificiais Autoencoders

by

Neste capítulo vamos estudar os tipos principais de Autoencoders (estamos considerando que você leu o capítulo anterior):

Os Autoencoders codificam os valores de entrada x usando uma função f. Em seguida, decodificam os valores codificados f (x) usando uma função g para criar valores de saída idênticos aos valores de entrada. O objetivo do Autoencoder é minimizar o erro de reconstrução entre a entrada e a saída. Isso ajuda os Autoencoders a aprender os recursos importantes presentes nos dados. Quando uma representação permite uma boa reconstrução de sua entrada, ela retém grande parte das informações presentes na entrada.

E existem diferentes tipos de Autoencoders. Confira:

1. Autoencoder Padrão

Na sua forma mais simples, o Autoencoder é uma rede neural artificial de três camadas, isto é, uma rede neural com uma camada de entrada, uma oculta e uma camada de saída. A entrada e a saída são as mesmas e aprendemos a reconstruir a entrada, por exemplo, usando o otimizador adam e a função de perda de erro quadrático médio.

2. Autoencoder Multicamada

Se uma camada oculta não for suficiente, obviamente podemos estender o Autoencoder para mais camadas ocultas. Nossa implementação poderia usar 3 camadas ocultas em vez de apenas uma. Qualquer uma das camadas ocultas pode ser escolhida como representação de recurso, mas o ideal é tornar a rede simétrica e usar a camada mais intermediária.

3. Autoencoder Convolucional

Também podemos nos perguntar: os Autoencoders podem ser usados com convoluções em vez de camadas totalmente conectadas?

A resposta é sim e o princípio é o mesmo, mas usando imagens (vetores 3D) em vez de vetores 1D achatados (flattened). A imagem de entrada é reduzida para fornecer uma representação latente de dimensões menores e forçar o Autoencoder a aprender uma versão compactada das imagens.

4. Autoencoder Regularizado

Existem outras maneiras pelas quais podemos restringir a reconstrução de um Autoencoder, além de impor uma camada oculta de menor dimensão que a entrada. Em vez de limitar a capacidade do modelo mantendo o codificador e o decodificador rasos e o tamanho do código pequeno, os Autoencoders regularizados usam uma função de perda que incentiva o modelo a ter outras propriedades além da capacidade de copiar sua entrada para sua saída. Na prática, geralmente encontramos dois tipos de Autoencoder Regularizado: o Autoencoder Esparso e o Autoencoder Denoising.

4.1. Autoencoder Esparso

Os Autoencoders Esparsos geralmente são usados ​​para aprender recursos para outra tarefa, como classificação. Um Autoencoder que foi regularizado para ser esparso deve responder a recursos estatísticos exclusivos do conjunto de dados em que foi treinado, em vez de simplesmente atuar como uma função de identidade. Dessa forma, o treinamento para executar a tarefa de cópia com uma penalidade de escassez pode produzir um modelo que aprendeu recursos úteis como subproduto.

Outra maneira de restringir a reconstrução do Autoencoder é impor uma restrição à sua perda. Poderíamos, por exemplo, adicionar um termo de reguralização na função de perda. Isso fará com que nosso Autoencoder aprenda representação esparsa de dados. Em nossa camada oculta, podemos adicionar um regularizador de atividades L1, que aplicará uma penalidade na função de perda durante a fase de otimização. Como resultado, a representação será mais esparsa em comparação com o Autoencoder Padrão. Abaixo uma representação do Autoencoder Esparso:

esparso

4.2. Autoencoder Denoising

Em vez de adicionar uma penalidade à função de perda, podemos obter um Autoencoder que aprende algo útil alterando o termo do erro de reconstrução da função de perda. Isso pode ser feito adicionando algum ruído à imagem de entrada e fazendo o Autoencoder aprender a removê-la. Dessa maneira, o Autoencoder extrairá os recursos mais importantes e aprenderá uma representação robusta dos dados.

Denoising refere-se à adição intencional de ruído à entrada bruta antes de fornecê-la à rede. Pode-se obter denoising usando o mapeamento estocástico. Abaixo uma representação do Autoencoder Denoising:

denoising

5. Contractive Autoencoders(CAE)

O objetivo do Autoencoder Contrativo (CAE) é ter uma representação aprendida robusta, menos sensível a pequenas variações nos dados. A robustez da representação para os dados é feita aplicando um termo de penalidade à função de perda. O termo da penalidade é a norma Frobenius da matriz jacobiana. A norma de Frobenius da matriz jacobiana para a camada oculta é calculada em relação à entrada. A norma de Frobenius da matriz jacobiana é a soma do quadrado de todos os elementos.

O Autoencoder Contrativo é outra técnica de regularização, como os Autoencoders Esparsos e os Autoencoders Denoising.

O CAE supera os resultados obtidos pela regularização do Autoencoder usando decaimento de peso ou denoising. O CAE é uma escolha melhor do que o Autoencoder Denoising para aprender a extração de recursos úteis. O termo de penalidade gera mapeamento que contrai fortemente os dados e, portanto, o nome Autoencoder Contrativo.

6. Deep Autoencoders

Deep Autoencoders consistem em duas redes de crenças profundas idênticas (Deep Belief Networks). Uma rede para codificação e outra para decodificação. Os Autoencoders tipicamente profundos têm de 4 a 5 camadas para codificação e as próximas 4 a 5 camadas para decodificação. Usamos camada não supervisionada por camada, pré-treinamento.

A Máquina Boltzmann Restrita (RBM) é o alicerce básico das Deep Belief Networks. Na figura abaixo, tiramos uma imagem com 784 pixels. Treinamos usando uma pilha de 4 RBMs, desenrolamos e ajustamos com Backpropagation. A camada de codificação final é compacta e rápida!

deep

7. Variational Autoencoders (VAEs)

Nos últimos anos, modelos generativos baseados em aprendizado profundo ganharam cada vez mais interesse devido a (e implicando) algumas melhorias surpreendentes no campo. Contando com uma enorme quantidade de dados, arquiteturas de rede bem projetadas e técnicas de treinamento inteligentes, os modelos geradores profundos demonstraram uma capacidade incrível de produzir peças de conteúdo altamente realistas de vários tipos, como imagens, textos e sons. Entre esses modelos geradores profundos, duas famílias principais se destacam e merecem uma atenção especial: Redes Adversárias Generativas (GANs) e Autoencoders Variacionais (VAEs). As GANs já estudamos nos capítulos anteriores.

E a VAE é tão especial que merece um capítulo inteiro. Não perca o próximo capítulo.

Referências:

Formação Engenheiro de Inteligência Artificial

Customizando Redes Neurais com Funções de Ativação Alternativas

Autoencoders – Unsupervised Learning

Deep inside: Autoencoders

Deep Learning — Different Types of Autoencoders

Contractive Auto-Encoders – Explicit Invariance During Feature Extraction

Stacked Denoising Autoencoders: Learning Useful Representations in a Deep Network with a Local Denoising Criterion

Introduction to Autoencoders

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Recurrent neural network based language model

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 52 – Arquitetura de Redes Neurais Gated Recurrent Unit (GRU)

by

Neste capítulo estudaremos um tipo realmente fascinante de rede neural. Introduzido por Cho, et al. em 2014, a GRU (Gated Recurrent Unit) visa resolver o problema da dissipação do gradiente que é comum em uma rede neural recorrente padrão. A GRU também pode ser considerada uma variação da LSTM porque ambas são projetadas de maneira semelhante e, em alguns casos, produzem resultados igualmente excelentes. Para acompanhar este capítulo você precisa ter concluído os capítulos anteriores.

O Problema, Memória de Curto Prazo

Redes neurais recorrentes sofrem de memória de curto prazo. Se uma sequência for longa o suficiente, elas terão dificuldade em transportar informações das etapas anteriores para as posteriores. Portanto, se você estiver tentando processar um parágrafo de texto para fazer previsões, as RNNs poderão deixar de fora informações importantes desde o início.

Durante a etapa de backpropagation, as redes neurais recorrentes sofrem com o problema da dissipação do gradiente. Gradientes são valores usados para atualizar os pesos das redes neurais. O problema da dissipação do gradiente é quando o gradiente diminui à medida que se propaga novamente ao longo do tempo. Se um valor de gradiente se torna extremamente pequeno, não contribui muito com o aprendizado.

Assim, nas redes neurais recorrentes, as camadas que recebem uma pequena atualização gradiente param de aprender. Portanto, como essas camadas não aprendem, as RNNs podem esquecer o que foi visto em sequências mais longas, tendo assim uma memória de curto prazo. 

LSTM e GRU Como Solução

LSTM e GRU foram criadas como a solução para a memória de curto prazo. Elas têm mecanismos internos chamados portões que podem regular o fluxo de informações.

 

rnns

 

Esses portões podem aprender quais dados em uma sequência são importantes para manter ou jogar fora. Ao fazer isso, eles podem transmitir informações relevantes ao longo de uma longa cadeia de sequências para fazer previsões. Quase todos os resultados de última geração baseados em redes neurais recorrentes são alcançados com essas duas redes. LSTM e GRU podem ser usadas em reconhecimento de voz, síntese de fala e geração de texto. Você pode até usá-las para gerar legendas em vídeos. Essas são aplicações de ponta em Inteligência Artificial.

Como as GRUs Funcionam?

A GRU é a nova geração de redes neurais recorrentes e é bastante semelhante a uma LSTM. As GRUs se livraram do estado da célula e usaram o estado oculto para transferir informações. Essa arquitetura possui apenas dois portões, um portão de redefinição (reset gate) e um portão de atualização (update date). As GRUs são uma versão melhorada da rede neural recorrente padrão. Mas o que as torna tão especiais e eficazes?

gru4

Para resolver o problema da dissipação do gradiente de uma RNN padrão, a GRU usa dois portões, reset e update gate. Basicamente, eles são dois vetores que decidem quais informações devem ser passadas para a saída. O que há de especial neles é que eles podem ser treinados para manter informações de muito tempo atrás, sem dissipá-las com o tempo ou remover informações irrelevantes para a previsão.

A estrutura da GRU permite capturar adaptativamente dependências de grandes sequências de dados sem descartar informações de partes anteriores da sequência. Isso é alcançado através de suas unidades de portões, semelhantes às das LSTMs. Esses portões são responsáveis por regular as informações a serem mantidas ou descartadas a cada etapa do tempo.

 

gru5

 

A capacidade da GRU de manter dependências ou memória de longo prazo decorre dos cálculos na célula da GRU para produzir o estado oculto. Enquanto as LSTMs têm dois estados diferentes passados entre as células – o estado da célula e o estado oculto, que carregam a memória de longo e curto prazo, respectivamente – as GRUs têm apenas um estado oculto transferido entre as etapas do tempo. Esse estado oculto é capaz de manter as dependências de longo e curto prazo ao mesmo tempo, devido aos mecanismos de restrição e cálculos pelos quais o estado oculto e os dados de entrada passam.

 

gruxlstm

 

Assim como os portões das LSTMs, os portões na GRU são treinados para filtrar seletivamente qualquer informação irrelevante, mantendo o que é útil. Esses portões são essencialmente vetores contendo valores entre 0 e 1 que serão multiplicados com os dados de entrada e / ou estado oculto. Um valor 0 nos vetores indica que os dados correspondentes no estado de entrada ou oculto não são importantes e, portanto, retornarão como zero. Por outro lado, um valor 1 no vetor significa que os dados correspondentes são importantes e serão usados.

No próximo capítulo veremos os detalhes matemáticos por trás da GRU, uma das arquiteturas mais interessantes de Deep Learning e que tem obtido resultados formidáveis especialmente em Processamento de Linguagem Natural.

Aqui você encontra uma animação que ajuda a compreender o funcionamento das arquiteturas de Deep Learning do tipo recorrente: Animated RNN, LSTM and GRU

Até o próximo capítulo!

Referências:

Formação Engenheiro de Inteligência Artificial

Customizando Redes Neurais com Funções de Ativação Alternativas

Understanding GRU Networks

Illustrated Guide to LSTM’s and GRU’s: A step by step explanation

Gated Recurrent Unit (GRU) 

A Recursive Recurrent Neural Network for Statistical Machine Translation

Sequence to Sequence Learning with Neural Networks

Recurrent Neural Networks Cheatsheet

On the difficulty of training recurrent neural networks

A Beginner’s Guide to LSTMs and Recurrent Neural Networks

Long Short-Term Memory (LSTM): Concept

Recurrent Neural Networks Tutorial, Part 1 – Introduction to RNNs

Recurrent Neural Networks Tutorial, Part 3 – Backpropagation Through Time and Vanishing Gradients

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Recurrent neural network based language model

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 51 – Arquitetura de Redes Neurais Long Short Term Memory (LSTM)

by

Estudamos as redes neurais recorrentes e suas limitações nos capítulos anteriores. Para superar alguns dos problemas das RNNs, podemos usar algumas de suas variações. Uma delas é chamada LSTM ou Long Short Term Memory, um tipo de rede neural recorrente, que é usada em diversos cenários de Processamento de Linguagem Natural. Neste capítulo estudaremos a Arquitetura de Redes Neurais Long Short Term Memory.

Precisamos de Memória

Os humanos não começam a pensar do zero a cada segundo. Ao ler este capítulo, você entende cada palavra com base em sua compreensão das palavras anteriores. Você não joga tudo fora e começa a pensar de novo a cada palavra que você lê. Seus pensamentos têm persistência.

As redes neurais tradicionais não podem fazer isso, o que dificulta sua aplicação para resolver diversos problemas. Por exemplo, imagine que você queira classificar o tipo de evento que está acontecendo em todos os pontos de um filme. Não está claro como uma rede neural tradicional poderia usar o aprendizado sobre eventos anteriores no filme para informar os posteriores.

Redes neurais recorrentes resolvem esse problema. São redes com loops, permitindo que as informações persistam.

Esses laços fazem com que as redes neurais recorrentes pareçam misteriosas. No entanto, se você pensar um pouco mais, perceberá que não são tão diferentes de uma rede neural normal. Uma rede neural recorrente pode ser imaginada como múltiplas cópias da mesma rede, cada uma passando uma mensagem a um sucessor. Considere o que acontece se desenrolarmos o loop:

 

RNN-unrolled

 

Essa natureza de cadeia revela que redes neurais recorrentes estão intimamente relacionadas a sequências e listas, uma arquitetura natural da rede neural a ser usada para esses dados.

Nos últimos anos, tem havido um incrível sucesso ao aplicar as RNNs a uma variedade de problemas: reconhecimento de fala, modelagem de idiomas, tradução, legendas de imagens… A lista continua. Deixarei a discussão sobre os incríveis feitos que podemos alcançar com as RNNs com o excelente post de Andrej Karpathy, The Unreasonable Effectiveness of Recurrent Neural Networks. 

Entretanto, boa parte do sucesso das RNNs se deve a uma de suas variações, as LSTMs, um tipo muito especial de rede neural recorrente que funciona, para muitas tarefas, muito melhor do que a versão padrão. Quase todos os resultados empolgantes baseados em redes neurais recorrentes são alcançados com LSTMs. Vamos então compreender o que torna as LSTMs tão especiais.

Arquitetura da LSTM

A LSTM é uma arquitetura de rede neural recorrente (RNN) que “lembra” valores em intervalos arbitrários. A LSTM é bem adequada para classificar, processar e prever séries temporais com intervalos de tempo de duração desconhecida. A insensibilidade relativa ao comprimento do gap dá uma vantagem à LSTM em relação a RNNs tradicionais (também chamadas “vanilla”), Modelos Ocultos de Markov (MOM) e outros métodos de aprendizado de sequências.

A estrutura de uma RNN é muito semelhante ao Modelo Oculto de Markov. No entanto, a principal diferença é como os parâmetros são calculados e construídos. Uma das vantagens da LSTM é a insensibilidade ao comprimento do gap. RNN e MOM dependem do estado oculto antes da emissão / sequência. Se quisermos prever a sequência após 1.000 intervalos em vez de 10, o modelo esqueceu o ponto de partida até então. Mas um modelo LSTM é capaz de “lembrar” por conta de sua estrutura de células, o diferencial da arquitetura LSTM.

A LSTM possui uma estrutura em cadeia que contém quatro redes neurais e diferentes blocos de memória chamados células.

 

lstmcell

 

A informação é retida pelas células e as manipulações de memória são feitas pelos portões (gates). Existem três portões:

Forget Gate: As informações que não são mais úteis no estado da célula são removidas com o forget gate. Duas entradas: x_t (entrada no momento específico) e h_t-1 (saída de célula anterior) são alimentadas ao gate e multiplicadas por matrizes de peso, seguidas pela adição do bias. O resultante é passado por uma função de ativação que fornece uma saída binária. Se para um determinado estado de célula a saída for 0, a informação é esquecida e para a saída 1, a informação é retida para uso futuro.

Input Gate: A adição de informações úteis ao estado da célula é feita pelo input gate. Primeiro, a informação é regulada usando a função sigmoide que filtra os valores a serem lembrados de forma similar ao forget gate usando as entradas h_t-1 e x_t. Então, um vetor é criado usando a função tanh que dá saída de -1 a +1, que contém todos os valores possíveis de h_t-1 e x_t. Os valores do vetor e os valores regulados são multiplicados para obter as informações úteis

Output Gate: A tarefa de extrair informações úteis do estado da célula atual para ser apresentadas como uma saída é feita pelo output gate. Primeiro, um vetor é gerado aplicando a função tanh na célula. Então, a informação é regulada usando a função sigmóide que filtra os valores a serem lembrados usando as entradas h_t-1 e x_t. Os valores do vetor e os valores regulados são multiplicados para serem enviados como uma saída e entrada para a próxima célula.

A célula RNN recebe duas entradas, a saída do último estado oculto e a observação no tempo = t. Além do estado oculto, não há informações sobre o passado para se lembrar. A memória de longo prazo é geralmente chamada de estado da célula. As setas em loop indicam a natureza recursiva da célula. Isso permite que as informações dos intervalos anteriores sejam armazenadas na célula LSTM. O estado da célula é modificado pelo forget gate colocado abaixo do estado da célula e também ajustado pela porta de modulação de entrada. Da equação, o estado da célula anterior esquece, multiplica-se com a porta do esquecimento e adiciona novas informações através da saída das portas de entrada.

Algumas das famosas aplicações das LSTMs incluem:

  • Modelagem de Linguagem
  • Tradução de Idiomas
  • Legendas em Imagens
  • Geração de Texto
  • Chatbots

Continuamos no próximo capítulo!

Referências:

Formação Engenheiro de Inteligência Artificial

Customizando Redes Neurais com Funções de Ativação Alternativas

A Recursive Recurrent Neural Network for Statistical Machine Translation

Sequence to Sequence Learning with Neural Networks

Recurrent Neural Networks Cheatsheet

On the difficulty of training recurrent neural networks

A Beginner’s Guide to LSTMs and Recurrent Neural Networks

Long Short-Term Memory (LSTM): Concept

Recurrent Neural Networks Tutorial, Part 1 – Introduction to RNNs

Recurrent Neural Networks Tutorial, Part 3 – Backpropagation Through Time and Vanishing Gradients

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Recurrent neural network based language model

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 48 – Redes Neurais Recorrentes

by

A partir deste capítulo estudaremos diversas outras arquiteturas de Deep Learning, que estão sendo usadas em aplicações de Inteligência Artificial de última geração. Continue conosco nessa incrível jornada.

Os humanos não começam a pensar do zero a cada segundo. Ao ler este texto, você entende cada palavra com base em sua compreensão das palavras anteriores. Você não joga tudo fora e começa a pensar de novo. Seus pensamentos têm persistência.

As redes neurais artificiais tradicionais não podem fazer isso, o que traz algumas limitações para esses tipos de modelos. Por exemplo, imagine que você queira classificar o tipo de evento que está acontecendo em todos os pontos de um filme. Não está claro como uma rede neural tradicional poderia usar seu raciocínio sobre eventos anteriores no filme para informar os posteriores.

Redes Neurais Recorrentes resolvem esse problema. São redes com loops, permitindo que as informações persistam.

As redes recorrentes são um tipo de rede neural artificial projetada para reconhecer padrões em sequências de dados, como texto, genomas, caligrafia, palavra falada ou dados de séries numéricas que emanam de sensores, bolsas de valores e agências governamentais. Esses algoritmos consideram tempo e sequência, eles têm uma dimensão temporal.

A pesquisa mostra que eles são um dos tipos mais poderosos e úteis de rede neural, juntamente com o mecanismo de atenção e as redes de memória. As RNNs são aplicáveis até mesmo a imagens, que podem ser decompostas em uma série de amostras e tratadas como uma sequência.

Como as redes recorrentes possuem um certo tipo de memória, e a memória também faz parte da condição humana, faremos analogias com a memória do cérebro, para uma melhor compreensão. Continue a leitura. 

Revisão de Redes Feedforward

Para entender as redes recorrentes, primeiro vamos revisar o básico das redes feedforward, que estudamos em capítulos anteriores aqui mesmo no Deep Learning Book.

Ambas as redes recebem o nome da forma como canalizam informações através de uma série de operações matemáticas realizadas nos nós da rede. As redes feedforward alimentam informações diretamente (nunca tocando em um determinado nó duas vezes), enquanto as redes recorrentes percorrem através de um loop.

No caso de redes feedforward, exemplos de entrada são alimentados na rede e transformados em uma saída; com a aprendizagem supervisionada, a saída seria por exemplo um rótulo, um nome aplicado à entrada. Ou seja, elas mapeiam dados brutos para categorias, reconhecendo padrões que podem sinalizar, por exemplo, que uma imagem de entrada deve ser rotulada como “gato” ou “cachorro”. A imagem abaixo mostra um exemplo de rede feedforward.

 

Rede Feed Forward

 

Uma rede feedforward pode então ser treinada em imagens rotuladas, por exemplo, até minimizar o erro ao classificar suas categorias. Com o conjunto treinado de parâmetros (ou pesos, conhecidos coletivamente como um modelo), a rede procura categorizar os dados que nunca viu. Uma rede feedforward treinada pode ser exposta a qualquer coleção aleatória de fotografias, e a primeira fotografia a que está exposta não alterará necessariamente como classifica a segunda. Ver a fotografia de um gato não levará a rede a perceber um cachorro em seguida.

Ou seja, uma rede feedforward não tem noção de ordem no tempo, e a única entrada que considera é o exemplo atual a que foi exposta. As redes feedforward são amnésicas em relação ao seu passado recente; elas lembram nostalgicamente apenas os momentos formativos do treinamento.

Redes Neurais Recorrentes

As redes recorrentes, por outro lado, tomam como entrada não apenas o exemplo de entrada atual que veem, mas também o que perceberam anteriormente no tempo. Aqui está um diagrama com a representação de uma rede neural recorrente e uma rede feedforward.

Nets

A decisão de uma rede recorrente alcançada na etapa de tempo t-1 afeta a decisão que alcançará um momento mais tarde na etapa de tempo t. Assim, as redes recorrentes têm duas fontes de entrada, o presente e o passado recente, que se combinam para determinar como respondem a novos dados, da mesma forma que fazemos na vida. Nas redes neurais recorrentes isso é feito, claro, com a ajuda da nossa querida Matemática. E por isso o curso Matemática Para Data Science é um dos cursos de maior sucesso na Data Science Academy.

As redes recorrentes são diferenciadas das redes feedforward pelo loop de feedback conectado às suas decisões anteriores, ingerindo suas próprias saídas momento após momento como entrada. Costuma-se dizer que as redes recorrentes têm memória. A adição de memória às redes neurais tem uma finalidade: há informações na própria sequência e as redes recorrentes a utilizam para executar tarefas que as redes de feedforward não conseguem.

Essa informação sequencial é preservada no estado oculto da rede recorrente, que consegue passar por muitas etapas de tempo à medida que ela avança em cascata para afetar o processamento de cada novo exemplo. Essas correlações entre eventos são separadas por muitos momentos, e essas correlações são chamadas de “dependências de longo prazo”, porque um evento no tempo depende e é uma função de um ou mais eventos que vieram antes. Uma maneira objetiva de pensar sobre as RNNs é a seguinte: elas são uma forma de compartilhar pesos ao longo do tempo.

Assim como a memória humana circula invisivelmente dentro de um corpo, afetando nosso comportamento sem revelar sua forma completa, a informação circula nos estados ocultos de redes recorrentes. A língua portuguesa está cheia de palavras que descrevem os ciclos de feedback da memória. Quando dizemos que uma pessoa é assombrada por seus atos, por exemplo, estamos simplesmente falando sobre as consequências que as produções passadas causam no tempo presente. Os franceses chamam isso de “Le passé qui ne passe pas” ou “O passado que não passa”.

Descreveremos o processo de levar a memória adiante matematicamente da seguinte forma:

O estado oculto na etapa de tempo t é h_t. É uma função da entrada na mesma etapa de tempo x_t, modificada por uma matriz de peso W (como a que usamos para redes feedforward) adicionada ao estado oculto do passo de tempo anterior h_t-1 multiplicado por seu próprio estado oculto – para a matriz de estado oculto U, também conhecida como matriz de transição e semelhante a uma cadeia de Markov. As matrizes de peso são filtros que determinam quanta importância deve ser dada tanto à entrada atual quanto ao estado oculto do passado. O erro que eles geram retornará por meio de retropropagação (backpropagation) e será usado para ajustar seus pesos até que o erro não diminua mais.

A soma da entrada de peso e do estado oculto é comprimida pela função φ – ou uma função sigmoide logística ou tanh, dependendo – que é uma ferramenta padrão para condensar valores muito grandes ou muito pequenos em um espaço logístico, bem como tornar os gradientes viáveis para retropropagação.

Como esse loop de feedback ocorre a cada etapa da série, cada estado oculto contém traços não apenas do estado oculto anterior, mas também de todos aqueles que precederam h_t-1 pelo tempo que a memória pode persistir.

Dada uma série de letras, uma rede recorrente usará o primeiro caractere para ajudar a determinar sua percepção do segundo caractere, de tal forma que um q inicial possa levá-lo a inferir que a próxima letra será u.

Mas para que as redes neurais recorrentes possam aprender de forma efetiva, precisamos de uma versão levemente modificada do Backpropagation, o BPTT (Backpropagation Through Time). Mas isso é assunto para o próximo capítulo! Estudaremos ainda duas importantes variações das RNNs, as Long Short-Term Memory Units (LSTMs) e as Gated Recurrent Units (GRUs).

Enquanto isso, caso queira começar a se divertir com as RNNs, acompanhe esse tutorial oficial do TensorFlow: Recurrent Neural Networks. Para aulas práticas em português com linguagem Python, acesse aqui.

Referências:

Formação Análise Estatística

Recurrent Neural Networks Cheatsheet

A Beginner’s Guide to LSTMs and Recurrent Neural Networks

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 47 – Reconhecimento de Imagens com Redes Neurais Convolucionais em Python – Parte 4

by

Vejamos como implementar nosso modelo de Rede Neural Convolucional que vai aprender a diferença nas imagens de cães e gatos e quando apresentarmos novas imagens ao modelo, ele será capaz de prever se a imagem é de um cão ou gato de forma automática.

O Jupyter Notebook completo está disponível com os demais arquivos do curso aqui. Abaixo você visualiza o Jupyter (use a barra de rolagem).


Com isso concluímos esta introdução a uma das mais famosas arquiteturas de Deep Learning, as Redes neurais Convolucionais. A partir do próximo capítulo estudaremos outras arquiteturas. Até lá.

Lembrando que a DSA oferece um programa completo para quem deseja aprender Deep Learning e Inteligência Artificial na prática e de forma profissional, a Formação Engenheiro de Inteligência Artificial. Faça como milhares de alunos no Brasil e no mundo e comece sua capacitação agora mesmo. O curso é 100% online e 100% em português. Seja um profissional em alta demanda!

Continuaremos no próximo capítulo.
Deep Learning Book

Capítulo 46 – Reconhecimento de Imagens com Redes Neurais Convolucionais em Python – Parte 3

by

Uma das principais dúvidas de quem está iniciando em Machine Learning e se depara com as Redes Neurais Convolucionais, é sobre como ocorre o aprendizado dos parâmetros (aquilo que o algoritmo realmente aprende durante o treinamento). O que exatamente está sendo feito quando apresentamos uma imagem a um algoritmo de Rede Neural Convolucional?

dogs_cats

Sabemos que em cada camada de convolução, a rede tenta entender os padrões básicos. Por exemplo: Na primeira camada de convolução, a rede tenta aprender padrões e bordas das imagens. Na segunda camada, ela tenta entender a forma / cor e outras coisas. Uma camada final chamada camada de recurso / camada totalmente conectada tenta classificar a imagem.

Antes de prepararmos o script com nossa rede convolucional, vamos compreender como definimos a arquitetura da rede e em quais camadas os parâmetros são aprendidos.

Camada de Entrada (Input Layer): O que a camada de entrada faz é ler a imagem. Portanto, não há parâmetros a serem aprendidos aqui.

Camada Convolucional (Convolutional Layer): considere uma camada convolucional que usa os mapas de recursos “l” como entrada e tem os mapas de recursos “k” como saída. O tamanho do filtro é “n * m”.

conv_layer

Aqui, a entrada tem l = 32 mapas de recursos como entradas, k = 64 mapas de recursos como saídas e o tamanho do filtro é n = 3 e m = 3. É importante entender que não temos apenas um filtro 3 * 3, mas, na verdade, temos um filtro 3 * 3 * 32, já que nossa entrada tem 32 dimensões. E como uma saída da primeira camada convolucional, aprendemos 64 diferentes filtros 3 * 3 * 32 cujo peso total é “n * m * k * l”. Depois, há um termo chamado bias para cada mapa de recursos. Portanto, o número total de parâmetros é “(n * m * l + 1) * k”.

Camada de Pooling (Pooling Layer): Não há parâmetros a aprender na camada de pooling. Essa camada é usada apenas para reduzir o tamanho da dimensão da imagem.

Obs: Podemos ter várias combinações de camada convolucional / camada de pooling em nossa arquitetura, sendo esta decisão do Cientista de Dados ou Engenheiro de Inteligência Artificial.

Camada Totalmente Conectada (Fully Connected Layer): Nesta camada, todas as unidades de entrada possuem um peso separável para cada unidade de saída. Para entradas “n” e saídas “m”, o número de pesos é “n * m”. Além disso, essa camada possui o bias para cada nó de saída, portanto, os parâmetros aprendidos são “(n + 1) * m”.

Camada de Saída (Output Layer): Esta camada é totalmente conectada, portanto, os parâmetros aprendidos também são “(n + 1) m”, quando “n” é o número de entradas e “m” é o número de saídas.

A principal dificuldade ao definir a arquitetura de um CNN é a primeira camada totalmente conectada. Não sabemos a dimensionalidade da camada totalmente conectada. Para calcular isso, temos que começar com o tamanho da imagem de entrada e calcular o tamanho de cada camada convolucional.

No caso simples, o tamanho da camada totalmente conectada é calculado como “input_size – (filter_size – 1)”. Por exemplo, se o tamanho da imagem de entrada for (50,50) e o filtro for (3,3), então (50- (3-1)) = 48. Mas o tamanho da imagem de entrada de uma rede convolucional não deve ser menor que a entrada, então precisamos definir o padding.

Para calcular o padding usamos: input_size + 2 * padding_size – (filter_size-1). Para o caso acima, (50 + (2 * 1) – (3–1) = 52 – 2 = 50) que fornece o mesmo tamanho de entrada. Perfeito, pois assim não perdemos nenhum detalhe da imagem. Se quisermos explicitamente diminuir a imagem durante a convolução, podemos definir um passo (stride).

Finalmente, para calcular o número de parâmetros que a rede vai aprender usamos: (n * m * k + 1) * f. Veremos tudo isso em código Python no próximo capítulo!

Caso queira mais detalhes sobre como definir a arquitetura da rede, consulte o famoso e excelente paper da AlexNet: ImageNet Classification with Deep Convolutional Neural Networks.

Referências:

Formação Machine Learning

ImageNet Classification with Deep Convolutional Neural Networks

Don’t Decay the Learning Rate, Increase the Batch Size

How to calculate the number of parameters in the CNN?

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 45 – Reconhecimento de Imagens com Redes Neurais Convolucionais em Python – Parte 2

by

Vamos iniciar nosso trabalho de Reconhecimento de Imagens com Redes Neurais Convolucionais em Python cuidando da nossa matéria-prima: dados. Precisamos fazer o download das imagens e organizá-las para então iniciar o trabalho.

Usaremos como fonte de dados, o famoso dataset Dogs and Cats oferecido pelo Kaggle, o portal sobre Competições de Data Science.

Você pode fazer o download das imagens neste endereço: Dogs vs. Cats. Mas nós já fizemos o download e disponibilizamos para você junto com o Jupyter Notebook no repositório deste livro aqui. Como este dataset é bastante famoso, alternativamente, você pode fazer o download oferecido pela Microsoft Research neste endereço Kaggle Cats and Dogs Dataset.

Feito o download das imagens (você vai precisar de aproximadamente 1 GB de espaço em disco para as imagens), precisamos organizar os arquivos em uma estrutura de diretórios da seguinte forma:

 

diretorios

 

Crie um diretório (por exemplo Cap45, mas pode ser o nome que você quiser). Dentro dele crie mais 3 pastas: dataset_treino, dataset_validation e dataset_teste. Não use espaços no nome e muito menos acentos nas palavras, pois isso causa diversos problemas em programação.

Dentro da pasta dataset_treino, crie mais duas pastas, cats (que vai receber as 12.500 imagens de gatos) e dogs (que vai receber as 12.500 imagens de cachorros). 

Nas pastas dataset_validation e dataset_teste não é necessário criar sub pastas e dentro delas colocaremos as 12.500 imagens de validação e 1.000 imagens de teste, respectivamente. As imagens de validação serão usadas para avaliar o modelo durante o treinamento e as imagens de teste serão usadas para avaliar o modelo depois do treinamento.

Podemos agora visualizar algumas imagens usando o Jupyter Notebook, que você encontra no repositório deste livro aqui. Caso não tenha familiaridade com o Jupyter Notebook, acesse o Capítulo 1 do curso gratuito Python Fundamentos Para Análise de Dados.

Se você criou a estrutura de diretórios de forma correta, então as seguintes células mostrarão algumas das imagens:

image1

 

image2

 

Se as imagens foram mostradas de forma correta, então os dados estão prontos para serem explorados. É o que faremos no próximo capítulo! Até lá.

Referências:

Análise de Imagens com Inteligência Artificial

Deep Learning Book

Capítulo 44 – Reconhecimento de Imagens com Redes Neurais Convolucionais em Python – Parte 1

by

Nossa tarefa é simples: vamos fornecer a um modelo de Deep Learning uma imagem e o modelo terá que classificar se a imagem é de um cachorro ou gato! Parece fácil, não? Na verdade, não! Para que isso funcione precisamos construir e treinar um modelo de Deep Learning, o que envolve conhecimentos de Matemática, Estatística, Programação, Visão Computacional, Pré-Processamento de imagens, entre outras áreas.

Mas nós vamos fazer isso juntos.

Nos próximos capítulos vamos construir e treinar um modelo de Deep Learning para Reconhecimento de Imagens com Redes Neurais Convolucionais em Python. Será uma excelente oportunidade de praticar tudo que estudamos no livro até aqui e preparar você para os capítulos mais avançados deste livro, quando estudaremos outras arquiteturas de Deep Learning.

Vamos começar?

Plano de Trabalho

Para começar, precisamos definir claramente o problema a ser resolvido e como vamos resolvê-lo.

Problema: Dada uma imagem, é um cachorro ou um gato?

A primeira coisa que precisamos é de muitas imagens de cachorros e gatos, para poder treinar um algoritmo de Deep Learning. Usaremos, portanto, uma abordagem de aprendizagem supervisionada, onde apresentaremos ao algoritmo diversas imagens, devidamente marcadas como sendo imagens de cães e gatos e então treinaremos o algoritmo. Ao final do treinamento, teremos um modelo que poderá receber novas imagens (desta vez não marcadas previamente) e então o modelo deverá ser capaz de classificar como sendo imagem de cão ou gato.

Para essa tarefa, usaremos uma arquitetura de Rede Neural Convolucional, a mesma que estudamos nos capítulos anteriores. Essa arquitetura usa métodos de convolução para poder prever características específicas de uma imagem de acordo com o que aprende em um conjunto de treinamento. Por exemplo, podemos dizer que é possível perceber a diferença ao procurar bigodes em um gato ou focinho comprido em um cachorro. Mas uma Rede Neural Convolucional procura muitos outros recursos baseados no que temos em um conjunto de treinamento.

Solução: Usar uma Rede Neural Convolucional para aprender recursos de imagens e assim prever se uma imagem contém um cachorro ou um gato.

Definição dos Dados

Data Science, Deep Learning, Machine Learning, Inteligência Artificial. Nada disso faz sentido sem dados, muitos dados (por isso Big Data é cada vez mais importante nos dias de hoje). E para esta tarefa, teremos os seguintes dados:

Conjunto de dados de treino: Teremos 12.500 imagens de cães e 12.500 imagens de gatos para o conjunto de treinamento.

Conjunto de dados de validação: Teremos 12.500 imagens de cães e gatos.

Conjunto de dados de teste: Teremos 1.000 imagens de cães e gatos.

Essa á uma questão onde os iniciantes tem muitas dúvidas. Por que precisamos de dados de treino, validação e teste? Usamos os dados de treino para treinar o algoritmo e então criar o modelo preditivo. Usamos os dados de validação, para avaliar o modelo durante o treinamento. Usamos os dados de teste para validar a performance do modelo já treinado, ou seja, apresentamos ao modelo dados que ele não viu durante o treinamento, a fim de garantir que ele é capaz de fazer previsões.

Estrutura de Trabalho

Vamos realizar as seguintes atividades na construção do modelo de Reconhecimento de Imagens com Redes Neurais Convolucionais em Python:

1- Visualização de Dados

Começaremos nosso trabalho com tarefas de visualização de dados e análise exploratória. Precisamos compreender os dados antes de qualquer outra coisa, como as dimensões das imagens, escala de cores, detalhes de sombras e se as imagens possuem mais detalhes não relacionados diretamente a um cachorro ou gato, como nesta imagem abaixo! Afinal, o modelo terá que aprender que um cachorro vestido de Hello Kitty ainda é um cachorro!

 

dog

 

2- Construindo a Rede Neural Convolucional

Nosso próximo passo será construir a arquitetura de rede. Definiremos quantas camadas serão usadas, camadas de convolução e pooling, funções de ativação, métrica de avaliação, descida do gradiente com backpropagation e outros detalhes. Discutiremos porque estamos fazendo nossas escolhas.

3- Treinamento

Com a arquitetura definida, podemos então treinar a nossa rede, o que consiste em apresentar os dados ao algoritmo para que o aprendizado ocorra. Definiremos os hiperparâmetros e por quanto tempo treinaremos a rede. Vamos aproveitar e discutir sobre técnicas para evitar o overfitting (quando o modelo se ajusta demais aos dados de treino).

4- Fazer Previsões

Por fim, usaremos o modelo treinado para fazer as classificações. Entregaremos ao modelo novas imagens e ele terá que classificar se a imagem é de um cachorro ou gato! Na prática, o modelo nunca faz a classificação com 100% de certeza. O que ele faz é uma previsão (para ser ainda mais preciso, uma inferência) e nosso trabalho é garantir que essa previsão tenha o mais alto nível de acurácia possível.

Ferramentas

Para este trabalho usaremos, claro, linguagem Python com Keras e TensorFlow. Vamos explicar a você quais são as opções de frameworks e cada linha de código será explicada em detalhes. Vamos considerar que você já conhece linguagem Python e sabe executar um Jupyter Notebook. Se não sabe, então acesse pelo menos o Capítulo 1 do nosso curso gratuito Python Fundamentos Para Análise de Dados.

Está pronto? Então nos encontramos no próximo capítulo!

Referências:

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 43 – Camadas de Pooling em Redes Neurais Convolucionais

by

Além das camadas convolucionais que acabamos de descrever nos capítulos anteriores, as redes neurais convolucionais também contêm camadas de agrupamento (ou Pooling). Camadas de Pooling são geralmente usadas imediatamente após camadas convolucionais e o que fazem é simplificar as informações na saída da camada convolucional.

Vejamos o que são e como funcionam as Camadas de Pooling em Redes Neurais Convolucionais e na sequência vamos colocar todas as camadas juntas para compreender como funciona todo o processo nesta importante arquitetura de Deep Learning.

A Camada de Pooling

Uma camada de pooling recebe cada saída do mapa de características da camada convolucional e prepara um mapa de características condensadas. Por exemplo, cada unidade na camada de pooling pode resumir uma região de (digamos) 2 × 2 neurônios na camada anterior. Como um exemplo concreto, um procedimento comum para o pooling é conhecido como pool máximo (ou Max-Pooling). No Max-Pooling, uma unidade de pooling simplesmente gera a ativação máxima na região de entrada 2 × 2, conforme ilustrado no diagrama a seguir:

 

pooling

 

Note que, como temos 24 × 24 neurônios emitidos da camada convolucional, após o agrupamento, temos 12 × 12 neurônios.

Como mencionado acima, a camada convolucional geralmente envolve mais do que um único mapa de características. Aplicamos o Max-Pooling para cada mapa de recursos separadamente. Portanto, se houvesse três mapas de recursos, as camadas combinadas, convolutional e Max-Pooling, se pareceriam com:

 

pooling2

 

Podemos pensar em Max-Pooling como uma forma de a rede perguntar se um determinado recurso é encontrado em qualquer lugar de uma região da imagem. Em seguida, elimina a informação posicional exata. A intuição é que, uma vez que um recurso tenha sido encontrado, sua localização exata não é tão importante quanto sua localização aproximada em relação a outros recursos. Um grande benefício é que há muito menos recursos agrupados e, portanto, isso ajuda a reduzir o número de parâmetros necessários nas camadas posteriores. Genial, não?

O Max-Pooling não é a única técnica usada para o pooling. Outra abordagem comum é conhecida como Pooling L2. Aqui, em vez de tomar a ativação máxima de uma região 2 × 2 de neurônios, tomamos a raiz quadrada da soma dos quadrados das ativações na região 2 × 2. Embora os detalhes sejam diferentes, a intuição é semelhante ao agrupamento máximo: o Pooling L2 é uma maneira de condensar informações da camada convolucional. Na prática, ambas as técnicas têm sido amplamente utilizadas. E às vezes as pessoas usam outros tipos de operação de Pooling.

Se você estiver realmente tentando otimizar o desempenho, poderá usar dados de validação para comparar várias abordagens diferentes ao Pooling e escolher a abordagem que funciona melhor. 

Juntando Tudo

Podemos agora juntar todas essas ideias para formar uma rede neural convolucional completa. É semelhante à arquitetura que estávamos estudando nos capítulos anteriores, mas tem a adição de uma camada de 10 neurônios de saída, correspondentes aos 10 valores possíveis para dígitos MNIST (‘0’, ‘1’, ‘2’, etc):

 

pooling3

 

A rede começa com 28 × 28 neurônios de entrada (cada image de cada dígito do dataset MNIST tem 28 x 28 pixels), que são usados ​​para codificar as intensidades de pixel para uma imagem no dataset MNIST. Este é então seguido por uma camada convolucional usando um campo receptivo local de 5 x 5 e três mapas de características. O resultado é uma camada de 3 × 24 × 24 neurônios ocultos. A próxima etapa é uma camada de Max-Pooling, aplicada a regiões 2 × 2, em cada um dos três mapas de recursos. O resultado é uma camada de 3 × 12 × 12 neurônios ocultos.

A camada final de conexões na rede é uma camada totalmente conectada. Ou seja, essa camada conecta todos os neurônios da camada de max-pooling a cada um dos 10 neurônios de saída. Essa arquitetura totalmente conectada é a mesma que usamos nos capítulos anteriores. Note, no entanto, que no diagrama acima, usei uma única seta, por simplicidade, em vez de mostrar todas as conexões. Claro, você pode facilmente imaginar as conexões.

Ou seja, temos uma rede composta de muitas unidades simples, cujos comportamentos são determinados por seus pesos e vieses. E o objetivo geral ainda é o mesmo: usar dados de treinamento para treinar os pesos e vieses da rede para que a rede faça um bom trabalho classificando os dígitos de entrada.

Em particular, assim como no início do livro, nós vamos treinar nossa rede usando descida estocástica do gradiente e retropropagação. Isso ocorre principalmente da mesma maneira que nos capítulos anteriores. No entanto, precisamos fazer algumas modificações no procedimento de retropropagação. A razão é que nossa derivação anterior da retropropagação foi para redes com camadas totalmente conectadas. Felizmente, é simples modificar a derivação para camadas convolucional e max-pooling. 

Quer ver tudo isso funcionando em linguagem Python? Então não perca o próximo capítulo!

Referências:

Análise de Imagens com Inteligência Artificial

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 42 – Compartilhamento de Pesos em Redes Neurais Convolucionais

by

Vamos continuar estudando Deep Learning e investigar como funciona o Compartilhamento de Pesos em Redes Neurais Convolucionais.

Já dissemos que cada neurônio tem um viés e pesos 5 × 5 conectados ao seu campo receptivo local. O que eu não mencionamos é que vamos usar os mesmos pesos e vieses para cada um dos 24 × 24 neurônios ocultos. Em outras palavras, para o neurônio oculto, a saída é:

 

form

 

Isso significa que todos os neurônios da primeira camada oculta detectam exatamente o mesmo recurso, apenas em locais diferentes na imagem de entrada. Para entender porque isso faz sentido, suponha que os pesos e os vieses sejam tais que o neurônio oculto possa escolher, digamos, uma borda vertical em um campo receptivo local específico. Essa habilidade também é útil em outros lugares da imagem. Por isso, é útil aplicar o mesmo detector de recursos em toda a imagem. Para colocar esse conceito em termos um pouco mais abstratos, as redes convolucionais são bem adaptadas à invariância da transalação das imagens: girar uma foto de um gato 90 graus, ainda faz dela a imagem de um gato, embora os pixels agora estejam organizados de forma diferente.

Por esse motivo, às vezes chamamos o mapa da camada de entrada para a camada oculta de um mapa de recursos. Chamamos os pesos que definem o mapa de recursos de pesos compartilhados. E nós chamamos o viés usado no mapa de recursos desta maneira de viés compartilhado. Os pesos e vieses compartilhados costumam definir um kernel ou filtro. Na literatura, as pessoas às vezes usam esses termos de maneiras ligeiramente diferentes e mais a frente veremos alguns exemplos concretos.

A estrutura de rede que descrevemos até agora pode detectar apenas um único tipo de recurso localizado. Para fazer reconhecimento de imagem, precisaremos de mais de um mapa de recursos. E assim, uma camada convolucional completa consiste em vários mapas de recursos, diferentes:

 

 

No exemplo mostrado acima, existem 3 mapas de recursos. Cada mapa de recursos é definido por um conjunto de pesos compartilhados de 5 × 5 e um único viés compartilhado. O resultado é que a rede pode detectar três tipos diferentes de recursos, sendo cada recurso detectável em toda a imagem.

No exemplo temos apenas 3 mapas de recursos, para manter o diagrama acima simples. No entanto, na prática, as redes convolucionais podem usar mais (e talvez muito mais) mapas de recursos. Uma das primeiras redes convolucionais, a LeNet-5, usou 6 mapas de recursos, cada um associado a um campo receptivo local 5 × 5, para reconhecer dígitos MNIST. Portanto, o exemplo ilustrado acima está bem próximo do LeNet-5. Nos exemplos que desenvolveremos mais adiante neste livro, usaremos camadas convolucionais com 20 e 40 mapas de recursos. Vamos dar uma olhada rápida em alguns dos recursos que são aprendidos:

 

features

 

As 20 imagens correspondem a 20 diferentes mapas de recursos (ou filtros ou kernels). Cada mapa é representado como uma imagem 5 × 5, correspondendo aos pesos 5 × 5 no campo receptivo local. Blocos mais brancos significam um peso menor (normalmente, mais negativo), portanto, o mapa de recursos responde menos aos pixels de entrada correspondentes. Blocos mais escuros significam um peso maior, portanto, o mapa de recursos responde mais aos pixels de entrada correspondentes. Muito grosso modo, as imagens acima mostram o tipo de características que a camada convolucional responde.

Então, o que podemos concluir desses mapas de recursos? Está claro que há estrutura espacial aqui além do que esperamos ao acaso: muitos dos recursos têm claras sub-regiões de luz e escuridão. Isso mostra que nossa rede realmente está aprendendo coisas relacionadas à estrutura espacial. No entanto, além disso, é difícil ver o que esses detectores de recursos estão aprendendo. De fato, agora há muito trabalho para entender melhor os recursos aprendidos pelas redes convolucionais. Se você estiver interessado em acompanhar esse trabalho, sugiro começar com o artigo Visualizando e Compreendendo Redes Convolucionais de Matthew Zeiler e Rob Fergus.

Uma grande vantagem do compartilhamento de pesos e vieses é que ele reduz bastante o número de parâmetros envolvidos em uma rede convolucional. Para cada mapa de recursos, precisamos de 5 × 5 = 25 pesos compartilhados, além de um único viés compartilhado. Portanto, cada mapa de recursos requer 26 parâmetros. Se temos 20 mapas de recursos, um total de 20 × 26 = 520 parâmetros define a camada convolucional. Em comparação, suponhamos que tivéssemos uma primeira camada totalmente conectada, com 784 = 28 × 28 neurônios de entrada e relativamente modestos 30 neurônios ocultos, como usamos em muitos dos exemplos anteriores no livro. Isso é um total de 784 × 30 pesos, além de um extra de 30 vieses, para um total de 23.550 parâmetros. Em outras palavras, a camada totalmente conectada teria mais de 40 vezes mais parâmetros que a camada convolucional.

É claro que não podemos fazer uma comparação direta entre o número de parâmetros, já que os dois modelos são diferentes em termos essenciais. Mas, intuitivamente, parece provável que o uso de invariância de tradução pela camada convolucional reduza o número de parâmetros necessários para obter o mesmo desempenho que o modelo totalmente conectado. Isso, por sua vez, resultará em um treinamento mais rápido para o modelo convolucional e, em última análise, nos ajudará a construir redes profundas usando camadas convolucionais.

A propósito, o nome convolucional vem do fato de que a operação na equação mostrada no início deste capítulo é às vezes conhecida como uma convolução. Um pouco mais precisamente, as pessoas às vezes escrevem essa equação como a1 = σ (b + w ∗ a0), onde a1 denota o conjunto de ativações de saída de um mapa de recursos, a0 é o conjunto de ativações de entrada e ∗ é chamado de operação de convolução. 

No próximo capítulo estudaremos as camadas de Pooling, outro “segredo” por trás das Redes Neurais Convolucionais e então estaremos prontos para colocar tudo isso junto. 

Referências:

Análise de Imagens com Inteligência Artificial

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 41 – Campos Receptivos Locais em Redes Neurais Convolucionais

by

Vamos estudar em detalhes a partir de agora as Redes Neurais Convolucionais, uma das principais arquiteturas de Deep Learning, amplamente usada em Visão Computacional. E começaremos compreendendo o que são os Campos Receptivos Locais. Mas antes, afinal, o que é Visão Computacional, amplamente usada em aplicações de Inteligência Artificial?

O Que é Visão Computacional?

Imagine a seguinte situação: você está em uma sala com mais duas pessoas. Uma delas arremessa uma bola e você a pega com as mãos. Nada poderia ser mais simples, certo?

Errado. Na verdade, este é um dos processos mais complexos que já tentamos compreender, ou seja, como o cérebro processa a visão de modo que sabemos exatamente o que é uma bola e quando ela está vindo em nossa direção? E ensinar uma máquina que seja capaz de ver da mesma forma que nós seres humanos é uma tarefa realmente difícil, não só porque é difícil fazer computadores executarem um cálculo matemático que reproduza a visão humana, mas porque não estamos inteiramente certos de como o processo da visão realmente funciona.

Primeiro vamos descrever de forma sucinta e aproximada como ocorre o processo de visão no caso do arremesso da bola: a imagem da esfera passa através de seu olho e chega a sua retina, que faz alguma análise elementar e envia o resultado ao cérebro, onde o córtex visual analisa mais profundamente a imagem. Em seguida, ele envia para o resto do córtex, que compara a tudo o que já sabe, classifica os objetos e dimensões e, finalmente, decide sobre algo a fazer: levantar a mão e pegar a bola (tendo previsto o seu caminho). Isso ocorre em uma pequena fração de segundo, com quase nenhum esforço consciente e quase nunca falha. Assim, recriar a visão humana não é apenas um problema difícil, é um conjunto deles, cada um dos quais depende do outro. 

A Visão Computacional é o processo de modelagem e replicação da visão humana usando software e hardware. A Visão Computacional é uma disciplina que estuda como reconstruir, interromper e compreender uma cena 3d a partir de suas imagens 2d em termos das propriedades da estrutura presente na cena.

Visão Computacional e reconhecimento de imagem são termos frequentemente usados como sinônimos, mas o primeiro abrange mais do que apenas analisar imagens. Isso porque, mesmo para os seres humanos, “ver” também envolve a percepção em muitas outras frentes, juntamente com uma série de análises. Cada ser humano usa cerca de dois terços do seu cérebro para o processamento visual, por isso não é nenhuma surpresa que os computadores precisariam usar mais do que apenas o reconhecimento de imagem para obter sua visão de forma correta.

O reconhecimento de imagens em si – a análise de pixel e padrão de imagens – é uma parte integrante do processo de Visão Computacional que envolve tudo, desde reconhecimento de objetos e caracteres até análise de texto e sentimento. O reconhecimento de imagem de hoje, ainda na maior parte, apenas identifica objetos básicos como “uma banana ou uma bicicleta em uma imagem.” Mesmo crianças podem fazer isso, mas o potencial da Visão Computacional é sobre-humano: ser capaz de ver claramente no escuro, através de paredes, em longas distâncias e processar todos esses dados rapidamente e em volume maciço. 

Já a Visão Computacional em seu sentido mais pleno está sendo usada na vida cotidiana e nos negócios para conduzir todos os tipos de tarefas, incluindo identificar doenças médicas em raios-x, identificar produtos e onde comprá-los, anúncios dentro de imagens editoriais, entre outros.

A Visão Computacional pode ser usada para digitalizar plataformas de mídia social a fim de encontrar imagens relevantes que não podem ser descobertas por meio de pesquisas tradicionais. A tecnologia é complexa e, assim como todas as tarefas acima mencionadas, requer mais do que apenas reconhecimento de imagem, mas também análise semântica de grandes conjuntos de dados. E a Visão Computacional é a principal técnica por trás dos veículos autônomos, que devem mudar completamente o mundo como o conhecemos.

Ninguém nunca disse que isso seria fácil. Exceto, talvez, Marvin Minsky, pioneiro da Inteligência Artificial, que, em 1966, instruía um estudante de pós-graduação a “conectar uma câmera a um computador e fazer com que descrevesse o que vê”. Mas a verdade é que 50 anos depois, ainda estamos trabalhando nisso, porém agora há uma diferença (ou duas talvez): temos Big Data e Processamento Paralelo em GPU’s. E acredite. Isso está realmente fazendo a diferença.

As Redes Neurais Convolucionais formam uma das arquiteturas de Deep Learning mais amplamente usada em tarefas de Visão Computacional e reconhecimento de imagens e a partir de agora vamos compreender porque.

Campos Receptivos Locais

Nas camadas totalmente conectadas mostradas no capítulo anterior, as entradas foram representadas como uma linha vertical de neurônios. Ou seja, convertemos uma imagem 28 x 28 (que é uma matriz) em um vetor de apenas uma dimensão (falaremos sobre isso mais adiante). Mas para compreender o que é um campo receptivo local, vamos considerar a imagem de seu formato padrão de 28x 28 (tamanho das imagens no dataset MNIST). Em uma imagem, cada pixel é um valor numérico que representa a intensidade de cor de acordo com a escala de cor utilizada, como RGB (Red – Green – Blue), por exemplo, ou apenas intensidade em escala de cinza para imagens em preto e branco.

rede1

Como de costume, vamos conectar os pixels de entrada a uma camada de neurônios ocultos. Mas não vamos conectar todos os pixels de entrada a cada neurônio oculto. Em vez disso, apenas fazemos conexões em regiões pequenas e localizadas da imagem de entrada.

Para ser mais preciso, cada neurônio na primeira camada oculta será conectado a uma pequena região dos neurônios de entrada, digamos, por exemplo, uma região de 5 × 5, correspondendo a 25 pixels de entrada. Assim, para um neurônio oculto em particular, podemos ter conexões que se parecem com isso:

rede2

Essa região na imagem de entrada é chamada de campo receptivo local para o neurônio oculto. É uma pequena janela nos pixels de entrada. Cada conexão aprende um peso e o neurônio oculto também aprende um viés (bias) geral. Você pode pensar nesse neurônio oculto particular como aprendendo a analisar seu campo receptivo local específico.

Em seguida, deslizamos o campo receptivo local por toda a imagem de entrada. Para cada campo receptivo local, existe um neurônio oculto diferente na primeira camada oculta. Para ilustrar isso concretamente, vamos começar com um campo receptivo local no canto superior esquerdo:

rede3

Então, deslizamos o campo receptivo local por um pixel para a direita (ou seja, por um neurônio), para conectar a um segundo neurônio oculto:

rede4

E assim por diante, construindo a primeira camada oculta. Observe que, se tivermos uma imagem de entrada 28 × 28 e campos receptivos locais 5 × 5, haverá 24 × 24 neurônios na camada oculta. Isso ocorre porque só podemos mover o campo receptivo local 23 neurônios para o lado (ou 23 neurônios para baixo), antes de colidir com o lado direito (ou inferior) da imagem de entrada.

Mostramos o campo receptivo local sendo movido por um pixel por vez. Na verdade, às vezes, um comprimento de passada diferente é usado. Por exemplo, podemos mover o campo receptivo local 2 pixels para a direita (ou para baixo), caso em que diríamos que um comprimento de passada de 2 é usado. Esse é um dos hyperparâmetros de uma rede neural convolucional, chamado stride length. No exemplo acima usado um stride length de 1, mas vale a pena saber que as pessoas às vezes experimentam comprimentos de passada diferentes.

Como foi feito nos capítulos anteriores, se estivermos interessados em testar comprimentos de passada diferentes, podemos usar os dados de validação para escolher o comprimento da passada que oferece o melhor desempenho. A mesma abordagem também pode ser usada para escolher o tamanho do campo receptivo local – não há, é claro, nada de especial sobre o uso de um campo receptivo local 5 × 5. Em geral, campos receptivos locais maiores tendem a ser úteis quando as imagens de entrada são significativamente maiores que as imagens MNIST de 28 × 28 pixels.

Eu já disse que cada neurônio oculto tem um viés e pesos 5 × 5 conectados ao seu campo receptivo local. O que eu ainda não mencionei é que vamos usar os mesmos pesos e vieses para cada um dos 24 × 24 neurônios ocultos. Quer saber como faremos isso matematicamente? Então não perca o próximo capítulo!

Referências:

Análise de Imagens com Inteligência Artificial

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 40 – Introdução às Redes Neurais Convolucionais

by

Nos primeiros capítulos deste livro ensinamos nossas redes neurais a fazer um bom trabalho reconhecendo imagens de dígitos manuscritos:

 

digits

 

Fizemos isso usando redes nas quais camadas adjacentes são totalmente conectadas umas às outras. Ou seja, todos os neurônios da rede estão conectados a todos os neurônios em camadas adjacentes:

 

rede

 

Em particular, para cada pixel na imagem de entrada, codificamos a intensidade do pixel como o valor de um neurônio correspondente na camada de entrada. Para as imagens de 28 × 28 pixels que estamos usando, isso significa que nossa rede tem 784 (= 28 × 28) neurônios de entrada. Em seguida, treinamos os pesos e vieses da rede para que a saída da rede identificasse corretamente a imagem de entrada: ‘0’, ‘1’, ‘2’, …, ‘8’ ou ‘9’.

Nossas redes anteriores funcionam muito bem: obtivemos uma precisão de classificação melhor que 98%, usando dados de treinamento e teste do conjunto de dados de dígitos manuscritos MNIST. Mas, após reflexão, é estranho usar redes com camadas totalmente conectadas para classificar imagens. A razão é que tal arquitetura de rede não leva em conta a estrutura espacial das imagens.

Por exemplo, ela trata os pixels de entrada que estão distantes e próximos exatamente no mesmo nível. Tais conceitos de estrutura espacial devem ser inferidos dos dados de treinamento. Mas e se, em vez de começarmos com uma arquitetura de rede que é rasa, utilizássemos uma arquitetura que tenta tirar proveito da estrutura espacial? É onde entram as redes neurais convolucionais.

Essas redes usam uma arquitetura especial que é particularmente bem adaptada para classificar imagens. O uso dessa arquitetura torna as redes convolucionais rápidas de treinar. Isso, por sua vez, nos ajuda a treinar redes profundas de muitas camadas, que são muito boas na classificação de imagens. Hoje, redes neurais convolucionais ou alguma variante próxima são usadas na maioria das redes neurais para reconhecimento de imagem.

As origens das redes neurais convolucionais remontam aos anos 70. Mas o artigo seminal que estabeleceu o tema moderno das redes convolucionais foi um artigo de 1998, “Gradient-based learning applied to document recognition“, de Yann LeCun, Léon Bottou, Yoshua Bengio e Patrick Haffner. Desde então, LeCun fez uma observação interessante sobre a terminologia para redes convolucionais: “A inspiração neural [biológica] em modelos como redes convolucionais é muito tênue. É por isso que eu os chamo de ‘redes convolucionais’ e não ‘redes neurais convolucionais’, e por isso os nós eu chamo de ‘unidades’ e não ‘neurônios’ “.

Apesar desta observação, as redes convolucionais usam muitas das mesmas ideias que as redes neurais que estudamos até agora: ideias como retropropagação, gradiente descendente, regularização, funções de ativação não lineares e assim por diante. E assim, vamos seguir a prática comum e considerá-las um tipo de rede neural. Usarei os termos “rede neural convolucional” e “rede convolucional” alternadamente. Também usarei os termos “neurônio [artificial]” e “unidade” alternadamente.

Definição

Uma Rede Neural Convolucional (ConvNet / Convolutional Neural Network / CNN) é um algoritmo de Aprendizado Profundo que pode captar uma imagem de entrada, atribuir importância (pesos e vieses que podem ser aprendidos) a vários aspectos / objetos da imagem e ser capaz de diferenciar um do outro. O pré-processamento exigido em uma ConvNet é muito menor em comparação com outros algoritmos de classificação. Enquanto nos métodos primitivos os filtros são feitos à mão, com treinamento suficiente, as ConvNets têm a capacidade de aprender esses filtros / características.

A arquitetura de uma ConvNet é análoga àquela do padrão de conectividade de neurônios no cérebro humano e foi inspirada na organização do Visual Cortex. Os neurônios individuais respondem a estímulos apenas em uma região restrita do campo visual conhecida como Campo Receptivo. Uma coleção desses campos se sobrepõe para cobrir toda a área visual. Veremos isso em detalhes mais a frente!

Por que usar ConvNets e não rede feed-forward?

Uma imagem não é nada além de uma matriz de valores de pixels, certo? Então, por que não apenas achatar a imagem (por exemplo, converter uma matriz 3×3 em um vetor 9×1. Se a image é uma matriz, nenhum problema em converter em uma vetor) e alimentá-lo para um Perceptron Multi-Layer para fins de classificação? Na verdade não.

Em casos de imagens binárias extremamente básicas, o método pode mostrar uma pontuação de precisão média durante a previsão de classes, mas teria pouca ou nenhuma precisão quando se trata de imagens complexas com dependências de pixel por toda parte.

Uma ConvNet é capaz de capturar com sucesso as dependências espaciais e temporais em uma imagem através da aplicação de filtros relevantes. A arquitetura executa um melhor ajuste ao conjunto de dados da imagem devido à redução no número de parâmetros envolvidos e à capacidade de reutilização dos pesos. Em outras palavras, a rede pode ser treinada para entender melhor a sofisticação da imagem.

 

rede2

 

Na figura acima, temos uma imagem RGB (Red – Green – Blue) que foi separada por seus três planos coloridos – Vermelho, Verde e Azul. Existem vários desses espaços de cores nos quais existem imagens – Escala de cinza, RGB, HSV, CMYK etc.

Você pode imaginar como a computação ficaria intensiva assim que as imagens atingissem dimensões, digamos, 8K (7680 × 4320). A função da ConvNet é reduzir as imagens para uma forma mais fácil de processar, sem perder recursos que são críticos para obter uma boa previsão. Isso é importante quando queremos projetar uma arquitetura que não seja apenas boa em recursos de aprendizado, mas que também seja escalável para conjuntos de dados massivos.

Essa é uma das arquiteturas de Deep Learning mais incríveis e com mais aplicações práticas e dedicaremos alguns capítulos a este arquitetura.

As redes neurais convolucionais usam três ideias básicas: campos receptivos locais, pesos compartilhados e pooling. Vamos dar uma olhada em cada uma dessas ideias? Então não perca os próximos capítulos!

Referências:

Análise de Imagens com Inteligência Artificial

Formação Análise Estatística

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

A Comprehensive Guide to Convolutional Neural Networks 

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 38 – O Efeito da Taxa de Aprendizagem no Treinamento de Redes Neurais Artificiais

by

Vamos retomar a discussão do capítulo anterior e tentar melhorar a precisão do modelo nos dados de teste a partir de um tamanho de lote maior, aumentando a taxa de aprendizado (learning rate). Vamos estudar O Efeito da Taxa de Aprendizagem no Treinamento de Redes Neurais Artificiais.

Algumas pesquisas na literatura sobre otimização em Machine Learning mostraram que aumentar a taxa de aprendizado pode compensar tamanhos maiores de lotes. Com isso em mente, aumentamos a taxa de aprendizado do nosso modelo para ver se podemos recuperar a precisão nos dados de teste (que havia sido reduzida quando aumentando o tamanho do lote). Os gráficos abaixo mostram as conclusões:

 

graf1

graf2

 

Curvas em laranja: tamanho do lote 64, taxa de aprendizagem 0.01 (referência)
Curvas em lilás: tamanho do lote 1024, taxa de aprendizado de 0,01 (referência)
Curvas em azul: tamanho do lote 1024, taxa de aprendizagem 0,1

As curvas em laranja e lilás são para referência e são as mesmas do conjunto de gráficos do capítulo anterior. Como a curva lilás, a curva azul treina com um tamanho de lote grande de 1024. No entanto, a curva azul tem uma taxa de aprendizado aumentada em 10 vezes. Curiosamente, podemos recuperar a precisão nos dados de teste a partir de um tamanho de lote maior, aumentando a taxa de aprendizado. Usando um tamanho de lote de 64 (laranja) atinge uma precisão de teste de 98%, enquanto o uso de um tamanho de lote de 1024 atinge apenas cerca de 96%. Mas aumentando a taxa de aprendizado, usando um tamanho de lote de 1024 também alcança uma precisão de teste de 98%. Assim como com nossa conclusão anterior, tenha cautela ao analisar esses resultados. Sabe-se que o simples aumento da taxa de aprendizado não compensa totalmente grandes tamanhos de lotes em conjuntos de dados mais complexos do que o MNIST.

E qual o efeito ao reduzir o tamanho do lote durante o treinamento do modelo?

A próxima pergunta interessante a ser feita é se o treinamento com lotes grandes “inicia você em um caminho ruim do qual você não pode se recuperar”. Ou seja, se começarmos a treinar com tamanho de lote 1024, então mudamos para tamanho de lote 64, podemos ainda alcançar a maior precisão em teste de 98%?

Investigamos três casos: treinar usando um tamanho de lote pequeno para uma única época, mudar para um tamanho de lote grande, treinar usando um tamanho de lote pequeno para muitas épocas e mudar para um tamanho maior de lote e treinar usando um tamanho grande de lote e então usar uma taxa de aprendizado mais alta com o mesmo tamanho de lote. Resultados abaixo:

 

graf3

graf4

 

  • Curvas em laranja: treinar em tamanho de lote 64 por 30 épocas (referência).
  • Curvas em amarelo neon: treinar em tamanho de lote 1024 por 60 épocas (referência).
  • Curvas em verde: treinar em tamanho de lote 1024 para 1 época e depois mudar para tamanho de lote 64 por 30 épocas (total de 31 épocas).
  • Curvas em amarelo escuro: treinar em tamanho de lote 1024 por 30 épocas e depois mudar para tamanho de lote 64 por 30 épocas (total de 60 épocas).
  • Curvas em lilás: treinamento em tamanho de lote 1024 e aumento da taxa de aprendizado em 10x na época 31 (total de 60 épocas).

Como antes, as curvas em laranja são para um tamanho de lote pequeno. As curvas em amarelo neon servem como um controle para garantir que não estamos melhorando a precisão do teste porque estamos simplesmente treinando mais. Se você prestar muita atenção ao eixo x, as épocas são enumeradas de 0 a 30. Isso ocorre porque somente as últimas 30 épocas de treinamento são mostradas. Para experimentos com mais de 30 épocas de treinamento no total, as primeiras x – 30 épocas foram omitidas.

É difícil ver as outras 3 linhas porque elas estão sobrepostas, mas não importa, porque nos três casos recuperamos a precisão em teste de 98%! Em conclusão, começar com um tamanho grande de lote não “pega o modelo preso” em alguma vizinhança de ótimos locais ideais. O modelo pode alternar para um tamanho de lote menor ou uma taxa de aprendizado mais alta a qualquer momento para obter uma precisão de teste melhor.

Para compreender o comportamento matemático por trás de todo esse processo, precisamos trazer o gradiente para esta discussão. É o que faremos no próximo capítulo. Até lá.

Referências:

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Effect of batch size on training dynamics

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 37 – O Efeito do Batch Size no Treinamento de Redes Neurais Artificiais

by

A partir deste capítulo você vai compreender em mais detalhes a arquitetura dos principais modelos de Deep Learning, com ênfase nas escolhas dos hiperparâmetros e abordagens de treinamento. Vamos começar com O Efeito do Batch Size no Treinamento de Redes Neurais Artificiais.

Neste experimento, vamos investigar o efeito do tamanho do lote (Batch Size) na dinâmica de treinamento. Tamanho do lote (Batch Size) é um termo usado em aprendizado de máquina e refere-se ao número de exemplos de treinamento usados em uma iteração. O Batch Size pode ser uma das três opções:

  • batch mode: onde o tamanho do lote é igual ao conjunto de dados total, tornando os valores de iteração e épocas equivalentes.
  • mini-batch mode: onde o tamanho do lote é maior que um, mas menor que o tamanho total do conjunto de dados. Geralmente, um número que pode ser dividido no tamanho total do conjunto de dados.
  • stochastic mode: onde o tamanho do lote é igual a um. Portanto, o gradiente e os parâmetros da rede neural são atualizados após cada amostra.

A métrica em que nos concentraremos é o gap de generalização, que é definido como a diferença entre o valor do tempo de treinamento e o valor do tempo de teste. Vamos investigar o tamanho do lote no contexto da classificação de imagens (o mesmo usado em diversos capítulos anteriores). Especificamente, usaremos o conjunto de dados MNIST.

No nosso caso, a diferença de generalização é simplesmente a diferença entre a precisão da classificação no tempo de teste e o tempo de treinamento. Estas experiências foram destinadas a fornecer alguma intuição básica sobre os efeitos do tamanho do lote. É bem conhecido na comunidade de aprendizado de máquina que a dificuldade de fazer afirmações gerais sobre os efeitos de hiperparâmetros geralmente varia de conjunto de dados a conjunto de dados e modelo a modelo. Portanto, as conclusões que fazemos aqui só podem servir como indicações em vez de declarações gerais sobre o tamanho do lote.

O tamanho do lote é um dos hiperparâmetros mais importantes para sintonizar os modernos sistemas de aprendizagem profunda. Os Cientistas de Dados muitas vezes querem usar um tamanho de lote maior para treinar seu modelo, uma vez que permite acelerações computacionais do paralelismo das GPUs. No entanto, é bem conhecido que um tamanho de lote muito grande levará a uma generalização deficiente (embora atualmente não se saiba exatamente porque isso acontece). Para as funções convexas que estamos tentando otimizar, há uma disputa inerente entre os benefícios de tamanhos de lotes menores e maiores.

Por um lado, usar um lote igual a todo o conjunto de dados garante a convergência para o ótimo global da função objetivo. No entanto, isso é à custa de uma convergência empírica mais lenta para esse ótimo. Por outro lado, o uso de tamanhos menores de lotes mostrou empiricamente uma convergência mais rápida para soluções “boas”. Isso é intuitivamente explicado pelo fato de que tamanhos de lote menores permitem que o modelo “inicie o aprendizado antes de ver todos os dados”. A desvantagem de usar um tamanho de lote menor é que não há garantia que o modelo vai convergir para o ótimo global. Ele irá saltar em torno do ótimo global, dependendo da relação entre o tamanho do lote e o tamanho do conjunto de dados.

Portanto, sob nenhuma restrição computacional, muitas vezes é aconselhável que se comece com um pequeno tamanho de lote, colhendo os benefícios de uma dinâmica de treinamento mais rápida, e aumente o tamanho do lote por meio de treinamento, aproveitando também os benefícios da convergência garantida.

Observou-se empiricamente que tamanhos de lote menores não só têm uma dinâmica de treinamento mais rápida, mas também generalização para o conjunto de dados de teste versus tamanhos de lote maiores. Mas esta afirmação tem seus limites. Sabemos que um tamanho de lote de 1 geralmente funciona muito mal. É geralmente aceito que existe um “ponto ideal” para o tamanho do lote entre 1 e todo o conjunto de dados de treinamento que fornecerá a melhor generalização. Esse “ponto ideal” geralmente depende do conjunto de dados e do modelo em questão.

A razão para uma melhor generalização é vagamente atribuída à existência de “ruído” no treinamento de pequeno tamanho de lote. Como os sistemas de redes neurais são extremamente propensos a ajustes excessivos (overfitting), a ideia é que a visualização de vários tamanhos de lote pequenos, cada lote sendo uma representação “ruidosa” de todo o conjunto de dados, causará uma espécie de dinâmica de “tug-and-pull”. Essa dinâmica evita que a rede neural se ajuste excessivamente no conjunto de treinamento e, portanto, tenha um desempenho ruim no conjunto de testes.

Definição do Problema

O problema exato que será investigado é o da classificação. Dada uma imagem X, o objetivo é prever o rótulo da imagem y. No caso do conjunto de dados MNIST, X são imagens em preto-e-branco dos dígitos 0 a 9 e y são as etiquetas de dígitos correspondentes “0” a “9”. Nosso modelo de escolha é uma rede neural. Especificamente, usaremos um Perceptron Multicamada (MLP). Salvo disposição em contrário, este é o modelo padrão foi usado no experimento:

  • 2 camadas ocultas totalmente conectadas (FC), 1024 unidades cada
  • Função de ativação ReLU
  • Função de perda: logaritmo negativo
  • Otimizador: SGD (Stochastic Gradient Descent)
  • Taxa de aprendizagem: 0,01
  • Épocas: 30

Em última análise, a pergunta que queremos responder é “qual tamanho de lote devo usar ao treinar uma rede neural?”

Efeito do Tamanho do Lote

A primeira coisa que devemos fazer para confirmar o problema que estamos tentando investigar é mostrar a dependência entre o intervalo de generalização e o tamanho do lote. Eu tenho me referido à métrica que estamos considerando como “gap de generalização”. Essa é tipicamente a medida de autores sobre o tema usada em artigos e papers, mas para simplicidade em nosso estudo nós apenas nos preocuparemos com a precisão do teste sendo a mais alta possível. Como veremos, a precisão de treinamento e teste dependerá do tamanho do lote, por isso é mais significativo falar sobre a precisão de teste em vez do gap de generalização. Mais especificamente, queremos que a precisão do teste depois de um grande número de épocas de treinamento, seja alta. Quantas épocas é um “grande número de épocas”? Idealmente, isso é definido como o número de épocas de treinamento necessárias, de modo que qualquer treinamento adicional forneça pouco ou nenhum aumento na precisão de teste. Na prática, isso é difícil de determinar e teremos que adivinhar quantas épocas são apropriadas para alcançar um comportamento ideal. Apresento as precisões de teste do nosso modelo de rede neural treinado usando diferentes tamanhos de lote abaixo (para aprender a fazer tudo isso na prática, clique aqui).

 

grafico

grafico2

 

Curvas em laranja: tamanho do lote 64
Curvas em verde: tamanho do lote 256
Curvas em lilás: tamanho do lote 1024

Descoberta: tamanhos maiores de lotes levam a uma precisão menor nos dados de teste.

O eixo x mostra o número de épocas de treinamento. O eixo y é rotulado para cada plotagem. MNIST é obviamente um conjunto de dados fácil de treinar; podemos alcançar 100% de precisão em treino e 98% em teste com apenas nosso modelo MLP base no tamanho de lote 64. Além disso, vemos uma clara tendência entre o tamanho do lote e a precisão do teste (e treinamento!). A nossa primeira conclusão é a seguinte: maiores tamanhos de lotes levam a uma menor precisão nos dados de teste. Esses padrões parecem existir em seu extremo para o conjunto de dados MNIST. Eu tentei tamanho de lote igual a 2 e alcançou uma precisão de teste ainda melhor de 99% (versus 98% para tamanho de lote 64)! Como aviso prévio, não espere que tamanhos de lote muito baixos, como 2, funcionem bem em conjuntos de dados mais complexos.

Mas neste experimento não consideramos alterações na taxa de aprendizagem. Poderíamos aumentar a acurácia em teste com tamanhos de lote maiores, ajustando a taxa de aprendizagem (learning rate)? Não perca o próximo capítulo para descobrir! Até lá.

Referências:

Don’t Decay the Learning Rate, Increase the Batch Size

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Effect of batch size on training dynamics

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning (material usado com autorização do autor)

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 36 – Outros Problemas com o Gradiente em Redes Neurais Artificiais

by

No capítulo anterior descrevemos para você a Matemática que ajuda a explicar a causa do problema da dissipação do gradiente. Mas a dissipação não é o único problema que pode ocorrer. Neste capítulo vamos descrever outros possíveis problemas com o gradiente em redes neurais artificiais.

Explosão do Gradiente

Vamos ver um exemplo explícito em que ocorre a explosão dos gradientes. O exemplo é bem simples e vamos alterar alguns parâmetros na rede de maneira a garantir que tenhamos a explosão do gradiente. Mesmo fazendo essa alteração para forçar o problema, a explosão do gradiente não é apenas uma possibilidade hipotética e realmente pode acontecer.

Há duas etapas para obter a explosão do gradiente. Primeiro, escolhemos todos os pesos na rede como grandes, digamos w1 = w2 = w3 = w4 = 100. Segundo, vamos escolher os vieses para que os termos σ ′ (zj) não sejam muito pequenos. Isso é realmente muito fácil de fazer: tudo o que precisamos é escolher os vieses para garantir que a entrada ponderada para cada neurônio seja zj = 0 (e então σ ′ (zj) = 1/4). Então, por exemplo, queremos z1 = w1a0 + b1 = 0. Podemos conseguir isso ajustando b1 = −100 ∗ a0. Podemos usar a mesma ideia para selecionar os outros vieses. Quando fazemos isso, vemos que todos os termos wjσ ′ (zj) são iguais a 100 ∗ 1/4 = 25. Com estas escolhas ocorre o problema da explosão do gradiente.

Instabilidade do Gradiente

O problema fundamental aqui não é tanto o problema do gradiente que desaparece ou o problema do gradiente que explode. É que o gradiente nas camadas iniciais é o produto dos termos de todas as camadas posteriores. Quando há muitas camadas, essa é uma situação intrinsecamente instável. A única maneira que todas as camadas podem aprender perto da mesma velocidade é se todos esses produtos de termos estiverem próximos de se equilibrar. Sem algum mecanismo ou razão subjacente para que o equilíbrio ocorra, é altamente improvável que aconteça simplesmente por acaso. Em suma, o problema real aqui é que as redes neurais sofrem de um problema de instabilidade do gradiente. Como resultado, se usarmos técnicas de aprendizado baseadas em gradiente padrão, camadas diferentes na rede tenderão a aprender em velocidades totalmente diferentes.

O Problema Mais Comum é Mesmo a Dissipação do Gradiente

Vimos que o gradiente pode desaparecer ou explodir nas camadas iniciais de uma rede profunda. De fato, ao usar neurônios sigmóides, o gradiente geralmente desaparece. Para ver porque, considere novamente a expressão | wσ ′ (z) |. Para evitar o problema da dissipação do gradiente, precisamos | wσ ′ (z) | ≥1. Você pode pensar que isso pode acontecer facilmente se w for muito grande. No entanto, é mais difícil do que parece. A razão é que o termo σ ′ (z) também depende de w: σ ′ (z) = σ ′ (wa + b), onde a é a ativação da entrada.

Então, quando fazemos w grande, precisamos ter cuidado para que não tornemos simultaneamente σ ′ (wa + b) pequeno. Isso acaba sendo uma restrição considerável. A razão é que quando fazemos w grande, tendemos a tornar o wa + b muito grande. Olhando para um gráfico de σ ′ você pode ver que isso nos coloca fora das “asas” da função σ ′, onde é preciso valores muito pequenos. A única maneira de evitar isso é se a ativação de entrada estiver dentro de um intervalo bastante estreito de valores. Às vezes isso vai acontecer, mas frequentemente, porém, isso não acontece. E assim, no caso genérico, temos a dissipação dos gradientes.

Gradientes Instáveis em Redes Mais Complexas

Temos estudado redes simples como exemplo, com apenas um neurônio em cada camada oculta. E quanto a redes profundas mais complexas, com muitos neurônios em cada camada oculta (tipicamente Deep Learning)?

network

 

De fato, o mesmo comportamento ocorre em tais redes. Nos capítulos anteriores onde estudamos retropropagação, vimos que o gradiente na camada l de uma rede de camada L é dado por:

form

Aqui, Σ ′ (zl) é uma matriz diagonal cujas entradas são os valores σ ′ (z) para as entradas ponderadas para a camada l. As wl são as matrizes de peso para as diferentes camadas. E ∇aC é o vetor de derivadas parciais de C em relação às ativações de saída.

Essa é uma expressão muito mais complicada do que no caso de um único neurônio. Ainda assim, se você olhar de perto, a forma essencial é muito semelhante, com muitos pares da forma:

form2

Além disso, as matrizes Σ′ (zj) possuem pequenas entradas na diagonal, nenhuma maior que 1/4. Desde que as matrizes de peso wj não sejam muito grandes, cada termo adicional:form3

tende a fazer o vetor gradiente menor, levando a uma dissipação do gradiente. Mais genericamente, o grande número de termos no produto tende a levar a um gradiente instável, assim como no nosso exemplo anterior. Na prática isso é tipicamente encontrado em redes sigmóides que os gradientes desaparecem exponencialmente de forma rápida nas camadas anteriores. Como resultado, o aprendizado diminui nessas camadas. Essa desaceleração não é apenas um acidente ou uma inconveniência: é uma consequência fundamental da abordagem que estamos adotando para o aprendizado da rede.

Outros Obstáculos Para a Aprendizagem Profunda

Nestes últimos capítulos, nos concentramos na dissipação de gradientes – e, em geral, gradientes instáveis – como um obstáculo à aprendizagem profunda. De fato, gradientes instáveis são apenas um obstáculo para o aprendizado profundo, embora seja um importante obstáculo fundamental. Muitas pesquisas em andamento têm como objetivo entender melhor os desafios que podem ocorrer quando se treinam redes profundas. Vamos mencionar brevemente alguns artigos, para dar a você o sabor de algumas das perguntas que as pessoas estão fazendo.

Como primeiro exemplo, em 2010 Glorot e Bengio encontraram evidências sugerindo que o uso de funções de ativação sigmóide pode causar problemas ao treinamento de redes profundas. Em particular, eles encontraram evidências de que o uso de sigmóides fará com que as ativações na camada oculta final saturem perto de 0 no início do treinamento, diminuindo substancialmente o aprendizado. Eles sugeriram algumas funções de ativação alternativas, que parecem não sofrer tanto com esse problema de saturação.

Como um segundo exemplo, em 2013, Sutskever, Martens, Dahl e Hinton estudaram o impacto na aprendizagem profunda tanto da inicialização de peso aleatório quanto do cronograma de momentum na descida de gradiente estocástica baseada no momento. Em ambos os casos, fazer boas escolhas fez uma diferença substancial na capacidade de treinar redes profundas.

Esses exemplos sugerem que “O que dificulta o treinamento de redes profundas?” é uma questão complexa. Nestes últimos capítulos, nos concentramos nas instabilidades associadas ao aprendizado baseado em gradiente em redes profundas. Os resultados dos dois últimos parágrafos sugerem que há também um papel desempenhado pela escolha da função de ativação, a forma como os pesos são inicializados e até mesmo detalhes de como a aprendizagem por gradiente descendente é implementada. E, claro, a escolha da arquitetura de rede e outros hiperparâmetros também é importante. Assim, muitos fatores podem desempenhar um papel em dificultar a formação de redes profundas, e a compreensão de todos esses fatores ainda é objeto de pesquisas em andamento. A boa notícia é que, a partir do próximo capítulo, vamos mudar isso e desenvolver várias abordagens para o aprendizado profundo que, até certo ponto, conseguem superar ou direcionar todos esses desafios.

Não é incrível o que estamos vivenciando neste exato momento da história humana? Tudo isso que estudamos até aqui forma a base de aplicações de Inteligência Artificial que já são encontradas no mercado, em diversas aplicações e até mesmo em nossos smartphones. E ainda estamos apenas no começo. 

E você, quer ou não fazer parte desta incrível revolução trazida pela Inteligência Artificial? Se a resposta for sim, o que está esperando?

Referências:

Formação Cientista de Dados

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning (material usado com autorização do autor)

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 54 – Introdução às Redes Adversárias Generativas (GANs – Generative Adversarial Networks)

by

 

Você pode não achar que os programadores são artistas, mas a programação é uma profissão extremamente criativa. É criatividade baseada em lógica. – John Romero

Redes Adversárias Generativas (GANs) são arquiteturas de redes neurais profundas compostas por duas redes colocadas uma contra a outra (daí o nome “adversárias”). Esta é uma das arquiteturas mais recentes e mais fascinantes em Deep Learning e que estudaremos a partir de agora!

As GANs foram introduzidos em um artigo de Ian Goodfellow e outros pesquisadores da Universidade de Montreal, incluindo Yoshua Bengio, em 2014. Referindo-se às GANs, o diretor de pesquisa de IA do Facebook, Yann LeCun, chamou o treinamento adversário de “a ideia mais interessante nos últimos 10 anos em Machine Learning”.

O potencial das GANs é enorme porque elas podem aprender a imitar qualquer distribuição de dados. Ou seja, as GANs podem ser ensinadas a criar mundos estranhamente semelhantes aos nossos em qualquer domínio: imagens, música, fala, prosa. Elas são artistas robóticos, em certo sentido, e sua produção é impressionante – até comovente.

Em uma virada surreal, a Christie’s (famosa rede inglesa de leilões) vendeu um retrato de US $ 432.000 gerado por uma GAN, com base no código-fonte aberto escrito por Robbie Barrat, de Stanford. Como a maioria dos artistas de verdade, ele não viu nada do dinheiro, que foi para a empresa francesa Obvious.

GANs

Dois dos nus gerados por GANs. Imagens de Robbie Barrat

Em 2019, o DeepMind mostrou que os Autoencoders Variacionais (VAEs) poderiam superar as GANs na geração de faces. Estudaremos os Autoencoders mais a frente aqui no livro.

Algoritmos Generativos vs. Discriminativos

Antes de entrar nos detalhes, vamos dar uma rápida visão geral do que são feitas as GANs. As Redes Adversárias Generativas pertencem ao conjunto de modelos generativos. Isso significa que eles são capazes de produzir / gerar (veremos como) novo conteúdo. Naturalmente, essa capacidade de gerar novo conteúdo faz com que as GANs pareçam um pouco “mágicas”, pelo menos à primeira vista. Nos capítulos seguintes superaremos a aparente mágica das GANs para mergulhar na matemática e modelagem por trás desses modelos. Não apenas discutiremos as noções fundamentais de que as Redes Adversárias Generativas se baseiam, mas estudaremos os conceitos principais dessa arquitetura passo a passo.

Para entender as GANs, você deve saber como os algoritmos generativos funcionam e, para isso, contrastá-los com algoritmos discriminativos é instrutivo. Algoritmos discriminativos tentam classificar os dados de entrada; isto é, dados os recursos de uma instância de dados, eles prevêem um rótulo ou categoria à qual esses dados pertencem. Praticamente tudo que estudamos no livro até aqui se refere a algoritmos discriminativos.

Por exemplo, dadas todas as palavras em um email (a instância de dados), um algoritmo discriminativo poderia prever se a mensagem é spam ou não é spam. O spam é um dos rótulos e o conjunto de palavras coletadas no email são os recursos que constituem os dados de entrada. Quando esse problema é expresso matematicamente, o rótulo é chamado y e os recursos são chamados x. A formulação p (y | x) é usada para significar “a probabilidade de y dado x”, que neste caso seria traduzido para “a probabilidade de um email ser spam, dadas as palavras que ele contém”.

Algoritmos discriminativos mapeiam recursos para rótulos e estão preocupados apenas com essa correlação. Uma maneira de pensar sobre algoritmos generativos é que eles fazem o oposto. Em vez de prever um rótulo com determinados recursos, eles tentam prever os recursos com um determinado rótulo.

A pergunta que um algoritmo generativo tenta responder é: Supondo que este email seja spam, qual a probabilidade desses recursos? Enquanto os modelos discriminativos se preocupam com a relação entre y e x, os modelos generativos se preocupam com “como você obtém x”. Eles permitem capturar p (x | y), a probabilidade de x dado y ou a probabilidade de recursos com um rótulo ou categoria. Dito isto, algoritmos generativos também podem ser usados ​​como classificadores. Acontece que eles podem fazer mais do que categorizar dados de entrada. O que mais eles podem fazer? Ainda estamos descobrindo, pois a evolução está acontecendo agora nesse momento com pesquisas em todo mundo e Cientistas de Dados e Engenheiros de IA trabalhando em diferentes aplicações.

Outra maneira de pensar sobre isso é distinguir discriminativo de generativo assim:

  • Modelos discriminativos aprendem a fronteira entre classes.
  • Modelos generativos modelam a distribuição de classes individuais.

Como as GANs Funcionam

Vejamos uma visão geral das GANs e nos próximos capítulos entraremos nos detalhes matemáticos e estatísticos da arquitetura.

Uma rede neural, chamada de gerador, gera novas instâncias de dados, enquanto a outra, o discriminador, avalia sua autenticidade; ou seja, o discriminador decide se cada instância de dados que ele analisa pertence ou não ao conjunto de dados de treinamento real (a imagem abaixo demonstra isso).

gan_schema

Digamos que estamos tentando fazer algo mais banal do que imitar a Mona Lisa. Geraremos números escritos à mão, como os encontrados no conjunto de dados MNIST, retirado do mundo real. O objetivo do discriminador, quando mostrada uma instância do verdadeiro conjunto de dados MNIST, é reconhecer aqueles que são autênticos.

Enquanto isso, o gerador está criando novas imagens sintéticas que são transmitidas ao discriminador. O gerador gera as imagens fake na esperança de que elas também sejam consideradas autênticas, mesmo sendo falsas. O objetivo do gerador é gerar dígitos manuscritos cada vez melhores. O objetivo do discriminador é identificar imagens falsas do gerador. Ou seja, são duas redes adversárias, uma discriminativa (padrão que já estudamos até aqui no livro) e uma generativa que, em termos gerais, faz o oposto das redes discriminativas.

Aqui estão as etapas de uma GAN:

  • O gerador considera números aleatórios e retorna uma imagem.
  • Essa imagem gerada é inserida no discriminador ao lado de um fluxo de imagens tiradas do conjunto de dados real e verdadeiro.
  • O discriminador obtém imagens reais e falsas e retorna probabilidades, um número entre 0 e 1, com 1 representando uma previsão de imagem autêntica e 0 representando previsão de imagens falsas (geradas pela rede generativa).

Então você tem um loop de feedback duplo assim:

GANs

Image credit: Thalles Silva

Para o MNIST, a rede discriminadora é uma rede convolucional padrão que pode categorizar as imagens alimentadas, um classificador binomial que rotula as imagens como reais ou falsas. O gerador é uma rede convolucional inversa, em certo sentido: enquanto um classificador convolucional padrão recebe uma imagem e reduz a amostragem para produzir uma probabilidade, o gerador pega um vetor de ruído aleatório e faz o upsample para uma imagem. O primeiro joga fora os dados por meio de técnicas de downsampling, como o maxpool, e o segundo gera novos dados.

Ambas as redes estão tentando otimizar uma função objetivo (função de perda) diferente e oposta. À medida que o discriminador muda seu comportamento, o gerador também muda e vice-versa. Suas perdas empurram um contra o outro. Uma ideia simples e genial! Durante o treinamento, a rede generativa vai aprendendo a criar uma imagem fake que fica cada vez mais próxima de uma imagem real. Alguns pesquisadores tem feito o mesmo com a voz, gerando falas que são falsas, mas se parecem muito com falas verdadeiras. Esse é o perigo das Deep Fakes, quando a tecnologia é usada para o mal, infelizmente. Aqui tem um exemplo de Deep Fake gerada com GAN para fala do ex-presidente dos EUA, Barack Obama: Fake Obama created using AI video tool – BBC News. 

gan

Quer aprender mais sobre as GANs? Então acompanhe os próximos capítulos!

Referências:

Cyber Security Data Science

Customizando Redes Neurais com Funções de Ativação Alternativas

A Beginner’s Guide to Generative Adversarial Networks (GANs)

A Leap into the Future: Generative Adversarial Networks

Understanding Generative Adversarial Networks (GANs)

How A.I. Is Creating Building Blocks to Reshape Music and Art

Train longer, generalize better: closing the generalization gap in large batch training of neural networks

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Recurrent neural network based language model

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Deep Learning Book

Capítulo 34 – O Problema da Dissipação do Gradiente

by

Então, por que as redes neurais profundas são difíceis de treinar?

Para responder a essa pergunta, primeiro revisitemos o caso de uma rede com apenas uma camada oculta. Como de costume, usaremos o problema de classificação de dígitos MNIST o mesmo já estudado nos capítulos anteriores.

A partir de um shell do Python, nós carregamos os dados MNIST:

 

mnist

 

Montamos nossa rede:

 

mnist

 

Esta rede possui 784 neurônios na camada de entrada, correspondendo a 28 × 28 = 784 pixels na imagem de entrada. Utilizamos 30 neurônios ocultos, assim como 10 neurônios de saída, correspondentes às 10 classificações possíveis para os dígitos MNIST (‘0’, ‘1’, ‘2’,…, ‘9’).

Vamos tentar treinar nossa rede por 30 épocas completas, usando mini-lotes de 10 exemplos de treinamento por vez, uma taxa de aprendizado η = 0.1 e um parâmetro de regularização λ = 5.0. À medida que treinarmos, monitoramos a precisão da classificação no conjunto de dados validation_data. Podemos executar o script test.py com todos os comandos. Via prompt de comando ou terminal, digitamos: python test.py (o treinamento pode levar muitos minutos dependendo da velocidade do computador).

 

treinamento

 

Ao final do treinamento, obtemos uma precisão de classificação de 96,48% (aproximadamente), comparável a nossos resultados anteriores com uma configuração semelhante. Agora, vamos adicionar outra camada oculta, também com 30 neurônios, e tentar treinar com os mesmos hiperparâmetros. Usamos:

 

net = network2.Network([784, 30, 30, 10])

 

Isto dá uma melhor precisão de classificação 96,90%. Isso é encorajador: um pouco mais de profundidade está ajudando. Vamos adicionar outra camada oculta de 30 neurônios.

 

net = network2.Network([784, 30, 30, 30, 10])

 

Isso não ajuda em nada. Na verdade, o resultado cai para 96,57%, próximo à nossa rede original. E suponha que inserimos mais uma camada oculta.

 

net = network2.Network([784, 30, 30, 30, 30, 10])

 

Esse comportamento parece estranho. Intuitivamente, camadas ocultas extras devem tornar a rede capaz de aprender funções de classificação mais complexas e, assim, fazer uma melhor classificação. Certamente, as coisas não devem piorar, já que as camadas extras podem, no pior dos casos, simplesmente não fazer nada. Mas não é isso que está acontecendo.

Então, o que está acontecendo? Vamos supor que as camadas ocultas extras realmente possam ajudar em princípio e o problema é que nosso algoritmo de aprendizado não está encontrando os pesos e vieses corretos. Gostaríamos de descobrir o que está errado em nosso algoritmo de aprendizado e como fazer melhor.

Para entender melhor o que está errado, vamos visualizar como a rede aprende. Abaixo, traçamos parte de uma rede [784,30,30,10], ou seja, uma rede com duas camadas ocultas, cada uma contendo 30 neurônios ocultos. Cada neurônio no diagrama tem uma pequena barra nele, representando a rapidez com que o neurônio está mudando à medida que a rede aprende. Uma barra grande significa que o peso e o viés do neurônio estão mudando rapidamente, enquanto uma barra pequena significa que os pesos e o viés estão mudando lentamente. Mais precisamente, as barras indicam o gradiente ∂C / ∂b para cada neurônio, ou seja, a taxa de mudança do custo em relação ao viés do neurônio.

Nos capítulos anteriores, vimos que essa quantidade de gradiente controlava não apenas a rapidez com que o viés muda durante o aprendizado, mas também a rapidez com que os pesos inseridos no neurônio também mudam. Não se preocupe se você não se lembrar dos detalhes: a única coisa a ter em mente é simplesmente que essas barras mostram a rapidez com que os pesos e os vieses de cada neurônio mudam conforme a rede aprende.

Para manter o diagrama simples, mostrei apenas os seis principais neurônios nas duas camadas ocultas. Eu omiti os neurônios de entrada, pois eles não têm pesos nem viés para aprender. Eu também omiti os neurônios de saída, já que estamos fazendo comparações por camadas, e faz mais sentido comparar camadas com o mesmo número de neurônios. Os resultados foram plotados no início do treinamento, ou seja, imediatamente após a inicialização da rede. Aqui estão eles:

 

rede

 

A rede foi inicializada aleatoriamente e, portanto, não é surpreendente que haja muita variação na rapidez com que os neurônios aprendem. Ainda assim, uma coisa que vale ressaltar é que as barras na segunda camada oculta são em sua maioria muito maiores que as barras na primeira camada oculta. Como resultado, os neurônios da segunda camada oculta aprendem um pouco mais rápido que os neurônios da primeira camada oculta. Isso é meramente uma coincidência, ou os neurônios da segunda camada oculta provavelmente aprenderão mais rápido do que os neurônios na primeira camada oculta em geral?

Para determinar se esse é o caso, é útil ter uma maneira global de comparar a velocidade de aprendizado na primeira e segunda camadas ocultas. Para fazer isso, vamos indicar o gradiente como δlj = ∂C / ∂blj, ou seja, o gradiente para o neurônio jth na camada lth.

Podemos pensar no gradiente δ1 como um vetor cujas entradas determinam a rapidez com que a primeira camada oculta aprende, e δ2 como um vetor cujas entradas determinam a rapidez com que a segunda camada oculta aprende. Em seguida, usaremos os comprimentos desses vetores como medidas globais da velocidade na qual as camadas estão aprendendo. Assim, por exemplo, o comprimento “δ1” mede a velocidade na qual a primeira camada oculta está aprendendo, enquanto o comprimento “δ2” mede a velocidade na qual a segunda camada oculta está aprendendo.

Com essas definições, e na mesma configuração que foi plotada acima, encontramos δδ1 = 0.07… e δδ2 = 0.31…. Isso confirma nossa suspeita anterior: os neurônios na segunda camada oculta realmente estão aprendendo muito mais rápido que os neurônios da primeira camada oculta.

O que acontece se adicionarmos mais camadas ocultas? Se tivermos três camadas ocultas, em uma rede [784,30,30,30,10], então as respectivas velocidades de aprendizado serão 0,012, 0,060 e 0,283. Novamente, as camadas ocultas anteriores estão aprendendo muito mais lentamente que as camadas ocultas posteriores. Suponha que adicionemos mais uma camada com 30 neurônios ocultos. Nesse caso, as respectivas velocidades de aprendizado são 0,003, 0,017, 0,070 e 0,285. O padrão é válido: as camadas iniciais aprendem mais lentamente que as camadas posteriores.

Temos observado a velocidade de aprendizado no início do treinamento, ou seja, logo após as redes serem inicializadas. Como a velocidade do aprendizado muda à medida que treinamos nossas redes? Vamos voltar para ver a rede com apenas duas camadas ocultas. A velocidade de aprendizado muda da seguinte forma:

 

training_speed_2_layers

 

Para gerar esses resultados, usamos a descida do gradiente em lote com apenas 1.000 imagens de treinamento, treinadas em mais de 500 épocas. Isso é um pouco diferente do que normalmente treinamos nos capítulos anteriores, mas acontece que o uso de gradiente estocástico em mini-lote dá resultados muito mais ruidosos (embora muito similares, quando você mede o ruído). Usar os parâmetros que escolhemos é uma maneira fácil de suavizar os resultados, para que possamos ver o que está acontecendo.

Em qualquer caso, como você pode ver, as duas camadas começam a aprender em velocidades muito diferentes (como já sabemos). A velocidade em ambas as camadas cai muito rapidamente, antes de se recuperar. Mas, apesar de tudo, a primeira camada oculta aprende muito mais lentamente do que a segunda camada oculta.

E quanto a redes mais complexas? Aqui estão os resultados de uma experiência semelhante, mas desta vez com três camadas ocultas (uma rede [784,30,30,30,10]):

 

training_speed_3_layers

 

Mais uma vez, as primeiras camadas ocultas aprendem muito mais lentamente do que as camadas ocultas posteriores. Finalmente, vamos adicionar uma quarta camada oculta (uma rede [784,30,30,30,30,10]) e ver o que acontece quando treinamos:

 

training_speed_4_layers

 

Mais uma vez, as primeiras camadas ocultas aprendem muito mais lentamente do que as camadas ocultas posteriores. Nesse caso, a primeira camada oculta está aprendendo aproximadamente 100 vezes mais lenta que a camada oculta final. Natural que estivéssemos tendo problemas para treinar essas redes antes!

Temos aqui uma observação importante: em pelo menos algumas redes neurais profundas, o gradiente tende a diminuir à medida que nos movemos para trás através das camadas ocultas. Isso significa que os neurônios nas camadas anteriores aprendem muito mais lentamente que os neurônios nas camadas posteriores. E, embora tenhamos visto isso em apenas uma única rede, há razões fundamentais pelas quais isso acontece em muitas redes neurais. O fenômeno é conhecido como O Problema da Dissipação do Gradiente ou The Vanishing Gradient Problem. Esse é um problema muito comum e ainda mais evidente em Redes Neurais Recorrentes, usadas em aplicações de Processamento de Linguagem Natural.

Por que o problema de dissipação do gradiente ocorre? Existem maneiras de evitar isso? E como devemos lidar com isso no treinamento de redes neurais profundas? Na verdade, aprenderemos rapidamente que não é inevitável, embora a alternativa também não seja muito atraente: às vezes, o gradiente fica muito maior nas camadas anteriores! Este problema é chamado de explosão do gradiente, e não é uma notícia muito melhor do que o problema da dissipação do gradiente. Geralmente, verifica-se que o gradiente em redes neurais profundas é instável, tendendo a explodir ou a desaparecer nas camadas anteriores. Essa instabilidade é um problema fundamental para o aprendizado baseado em gradiente em redes neurais profundas. É algo que precisamos entender e, se possível, tomar medidas para resolver.

Momentaneamente se afastando das redes neurais, imagine que estamos tentando minimizar numericamente uma função f(x) de uma única variável. Não seria uma boa notícia se a derivada f′(x) fosse pequena? Isso não significaria que já estávamos perto de um extremo? De forma semelhante, o pequeno gradiente nas primeiras camadas de uma rede profunda pode significar que não precisamos fazer muito ajuste dos pesos e vieses?

Claro, isso não é o caso. Lembre-se de que inicializamos aleatoriamente o peso e os vieses na rede. É extremamente improvável que nossos pesos e vieses iniciais façam um bom trabalho em qualquer coisa que desejamos que nossa rede faça. Para ser concreto, considere a primeira camada de pesos em uma rede [784,30,30,30,10] para o problema MNIST.

A inicialização aleatória significa que a primeira camada elimina a maior parte das informações sobre a imagem de entrada. Mesmo que as camadas posteriores tenham sido extensivamente treinadas, elas ainda acharão extremamente difícil identificar a imagem de entrada, simplesmente porque elas não possuem informações suficientes. E assim, não é possível que não seja preciso aprender muito na primeira camada. Se vamos treinar redes profundas, precisamos descobrir como resolver o problema da dissipação do gradiente.

Se eu fosse você, não perderia o próximo capítulo com uma explicação matemática para esse importante fenômeno no treinamento de redes neurais profundas (Deep Learning).

Referências:

Orquestração de Fluxos de Dados com Apache Airflow

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning (material usado com autorização do autor)

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 32 – Como Uma Rede Neural Artificial Encontra a Aproximação de Uma Função

by

Este é um capítulo muito importante para compreender como as redes neurais realmente funcionam e Como Uma Rede Neural Artificial Encontra a Aproximação de Uma Função. Acompanhe a explicação passo a passo analisando cada um dos gráficos apresentados.

Mas antes de explicar porque o teorema da universalidade é verdadeiro, quero mencionar duas advertências a esta declaração informal: “uma rede neural pode computar qualquer função”, que vimos no capítulo anterior.

Primeiro, isso não significa que uma rede possa ser usada para calcular exatamente qualquer função. Em vez disso, podemos obter uma aproximação que seja tão boa quanto desejamos. Aumentando o número de neurônios ocultos, podemos melhorar a aproximação. Por exemplo, anteriormente ilustramos uma rede computando alguma função f(x) usando três neurônios ocultos. Para a maioria das funções, apenas uma aproximação de baixa qualidade será possível usando três neurônios ocultos. Ao aumentar o número de neurônios ocultos (digamos, para cinco), podemos obter uma melhor aproximação:

rede

E podemos melhorar ainda mais aumentando o número de neurônios ocultos.

Para tornar esta afirmação mais precisa, suponha que tenhamos uma função f(x) que gostaríamos de computar com alguma precisão desejada ϵ > 0. A garantia é que usando neurônios ocultos suficientes sempre podemos encontrar uma rede neural cuja saída g(x) satisfaça | g(x) − f(x) | < ϵ, para todas as entradas x. Em outras palavras, a aproximação será boa dentro da precisão desejada para cada entrada possível.

A segunda ressalva é que a classe de funções que podem ser aproximadas da maneira descrita são as funções contínuas. Se uma função é descontínua, isto é, faz saltos bruscos e repentinos, então, em geral, não será possível aproximar usando uma rede neural. Isso não é surpreendente, já que nossas redes neurais calculam funções contínuas de sua entrada.

No entanto, mesmo que a função que realmente gostaríamos de computar fosse descontínua, muitas vezes a aproximação contínua é boa o suficiente. Se é assim, então podemos usar uma rede neural. Na prática, isso geralmente não é uma limitação importante.

Em suma, uma afirmação mais precisa do teorema da universalidade é que redes neurais com uma única camada oculta podem ser usadas para aproximar qualquer função contínua a qualquer precisão desejada. Neste e no próximo capítulo, vamos provar uma versão desse resultado.

Universalidade Com Uma Entrada e Uma Saída

Para entender por que o teorema da universalidade é verdadeiro, vamos começar entendendo como construir uma rede neural que se aproxima de uma função com apenas uma entrada e uma saída:

rede2

Este é o cerne do problema da universalidade. Uma vez que entendemos esse caso especial, é realmente fácil estender para funções com muitas entradas e muitas saídas (tema do próximo capítulo).

Para construir um insight sobre como construir uma rede para calcular f, vamos começar com uma rede contendo apenas uma camada oculta, com dois neurônios ocultos e uma camada de saída contendo um único neurônio de saída:

rede

Para ter uma ideia de como funcionam os componentes da rede, vamos nos concentrar no neurônio oculto superior. No diagrama abaixo, aumentando o valor de w, podemos ver imediatamente como a função computada pelo neurônio oculto superior muda:

rede

Como aprendemos anteriormente no livro, o que está sendo computado pelo neurônio oculto é σ(wx + b), onde σ(z) ≡ 1 / (1 + e^-z) é a função sigmóide. Até agora, fizemos uso frequente dessa forma algébrica. Mas, para a prova da universalidade, obteremos mais discernimento ignorando inteiramente a álgebra e, em vez disso, manipulando e observando a forma mostrada no gráfico. Isso não apenas nos dará uma ideia melhor do que está acontecendo, mas também nos dará uma prova de universalidade que se aplica a outras funções de ativação que não a função sigmóide.

Para começar esta prova, podemos aumentar o bias, b, no diagrama acima. Você verá que, conforme o bias aumenta, o gráfico se move para a esquerda, mas sua forma não muda.

Em seguida, podemos diminuir o viés (bias). Você verá que conforme o viés diminui, o gráfico se move para a direita, mas, novamente, sua forma não muda. Em seguida, diminuímos o peso para cerca de 2 ou 3. Você verá que à medida que diminui o peso, a curva se alarga. Talvez seja necessário alterar o bias também, para manter a curva no quadro.

Finalmente, aumentamos o peso acima de w = 100. A curva fica mais íngreme, até que, eventualmente, ela começa a parecer uma função de passo (Step Function). A imagem a seguir mostra como deve ser resultado:

rede3

Podemos simplificar um pouco nossa análise aumentando o peso para que a saída realmente seja uma Step Function, para uma aproximação muito boa. Abaixo eu plotei a saída do neurônio oculto superior quando o peso é w = 999. 

rede4

Na verdade, é um pouco mais fácil trabalhar com funções step do que com funções gerais sigmóides. A razão é que, na camada de saída, somamos contribuições de todos os neurônios ocultos. É fácil analisar a soma de várias funções step, mas é mais difícil pensar sobre o que acontece quando você adiciona um monte de curvas em forma de sigmóide.

E assim torna as coisas muito mais fáceis de assumir que nossos neurônios ocultos estão emitindo funções step. Mais concretamente, fazemos isso fixando o peso w como sendo um valor muito grande e, em seguida, definindo a posição da etapa modificando o bias. É claro que tratar a saída como uma função step é uma aproximação, mas é uma aproximação muito boa e, por enquanto, vamos tratá-la como exata. Voltarei mais tarde para discutir o impacto dos desvios dessa aproximação.

Em que valor de x a etapa ocorre? Em outras palavras, como a posição da etapa depende do peso e do viés?

Para responder a essa pergunta, podemos modificar o peso e o viés no diagrama acima. Você consegue descobrir como a posição da etapa depende de w e b. Com um pouco de trabalho, você deve ser capaz de se convencer de que a posição da etapa é proporcional a b e inversamente proporcional a w.

Na verdade, a etapa está na posição s = −b / w, como você pode ver modificando o peso e o bias no diagrama a seguir:

rede5

Isso simplificará muito nossas vidas para descrever os neurônios ocultos usando apenas um único parâmetro, s, que é a posição do passo, s = −b / w. 

rede6

Como mencionado acima, nós implicitamente definimos o peso w na entrada como um valor grande – grande o suficiente para que a função de passo seja uma boa aproximação. Podemos facilmente converter um neurônio parametrizado dessa maneira de volta ao modelo convencional, escolhendo o viés b = −ws.

Até agora, nos concentramos na saída apenas do neurônio oculto superior. Vamos dar uma olhada no comportamento de toda a rede. Em particular, vamos supor que os neurônios ocultos estejam computando funções de passos parametrizadas pelos pontos de degrau s1 (neurônio superior) e s2 (neurônio de baixo). E eles terão os respectivos pesos de saída w1 e w2. Aqui está a rede:

rede7

O que está sendo plotado à direita é a saída ponderada w1a1 + w2a2 da camada oculta. Aqui, a1 e a2 são as saídas dos neurônios ocultos superior e inferior, respectivamente. Essas saídas são frequentemente conhecidas como ativações dos neurônios.

Podemos aumentar ou diminuir o ponto de passo s1 do neurônio oculto superior e isso nos dá uma ideia de como isso altera a saída ponderada da camada oculta. Vale a pena entender o que acontece quando o s1 passa do s2. Você verá que o gráfico muda de forma quando isso acontece, já que nos movemos de uma situação em que o neurônio oculto superior é o primeiro a ser ativado para uma situação em que o neurônio oculto na parte inferior é o primeiro a ser ativado.

Da mesma forma, podemos manipular o ponto de passo s2 do neurônio oculto na parte inferior e ter uma ideia de como isso altera a saída combinada dos neurônios ocultos.

Finalmente, podemos definir w1 como 0.8 e w2 como −0.8. Você recebe uma função “bump”, que começa no ponto s1, termina no ponto s2 e tem a altura 0.8. Por exemplo, a saída ponderada pode ser assim:

rede8

Claro, podemos redimensionar o bump para ter qualquer altura. Vamos usar um único parâmetro, h, para indicar a altura. Para reduzir a confusão, também removerei as notações “s1 = …” e “w1 = …”.

rede9

Podemos alterar o valor de h para cima e para baixo, para ver como a altura do bump muda. 

Você notará, a propósito, que estamos usando nossos neurônios de uma forma que pode ser pensada não apenas em termos gráficos, mas em termos de programação mais convencionais, como uma espécie de declaração if-then-else, por exemplo:

code

Na maior parte eu vou ficar com o ponto de vista gráfico. Mas, no que se segue, às vezes você pode achar útil trocar pontos de vista e pensar sobre as coisas em termos de se-então-senão (uma das bases da programação convencional).

Podemos usar o nosso truque de fazer bump para obter dois solavancos, colando dois pares de neurônios ocultos na mesma rede:

rede11

Eu suprimi os pesos aqui, simplesmente escrevendo os valores h para cada par de neurônios ocultos. 

De maneira mais geral, podemos usar essa ideia para obter o máximo de picos que quisermos, de qualquer altura. Em particular, podemos dividir o intervalo [0,1] em um número grande, N, de subintervalos, e usar N pares de neurônios ocultos para configurar picos de qualquer altura desejada. Vamos ver como isso funciona para N = 5. Desculpa pela a complexidade do diagrama abaixo (eu poderia esconder a complexidade abstraindo mais, mas acho que vale a pena colocar um pouco de complexidade, para obter uma ideia mais concreta de como essas redes funciona):

rede

Você pode ver que existem cinco pares de neurônios ocultos. Os pontos escalonados para os respectivos pares de neurônios são 0,1 / 5, depois 1 / 5,2 / 5 e assim por diante, para 4 / 5,5 / 5. Esses valores são fixos – eles fazem com que tenhamos cinco saliências uniformemente espaçadas no gráfico.

Cada par de neurônios tem um valor de h associado a ele. Lembre-se, as conexões saídas dos neurônios têm pesos h e −h (não marcados). Ao alterar os pesos de saída, estamos realmente projetando a função!

Conforme alteramos as alturas, é possível ver a mudança correspondente nos valores h. E há também uma mudança nos pesos de saída correspondentes, que são + h e −h.

Em outras palavras, podemos manipular diretamente a função que aparece no gráfico à direita e ver isso refletido nos valores h à esquerda. 

Mas aqui consideramos uma entrada e uma saída, o que é bem simples. Com múltiplas entradas o conceito é basicamente o mesmo, mas iremos discutir as particularidades nos próximos capítulos, quando mergulharmos nas redes neurais profundas. Até lá.

Referências:

Construção e Deploy de Agentes de IA

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning (material utilizado com autorização do autor)

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 30 – Variações do Stochastic Gradient Descent – Hessian Optimization e Momentum

by

Cada técnica mostrada até aqui é valiosa e deve ser dominada por aqueles que pretendem trabalhar com redes neurais artificiais e aplicações de Inteligência Artificial, mas essa não é a única razão pela qual nós as explicamos.

O ponto principal é familiarizar você com alguns dos problemas que podem ocorrer nas redes neurais e com um estilo de análise que pode ajudar a superar esses problemas. De certo modo, aprendemos a pensar sobre redes neurais.

Agora neste capítulo, esquematizamos brevemente algumas outras técnicas. Esses esboços são menos aprofundados do que as discussões anteriores, mas devem transmitir algum sentimento pela diversidade de técnicas disponíveis para uso em redes neurais. Lembrando que você sempre pode estudar todas essas técnicas em detalhes nos cursos da Formação Engenheiro de Inteligência Artificial.

Variações do Stochastic Gradient Descent

A descida de gradiente estocástico pela retropropagação tem nos servido bem no ataque ao problema de classificação de dígitos do dataset MNIST. No entanto, existem muitas outras abordagens para otimizar a função de custo e, às vezes, essas outras abordagens oferecem desempenho superior ao gradiente estocástico em mini-lote. Neste capítulo discutiremos duas dessas abordagens, Hessian Optimization e Momentum.

Hessian Optimization

Para iniciar nossa discussão, ajuda a colocar as redes neurais de lado por um tempo. Em vez disso, vamos apenas considerar o problema abstrato de minimizar uma função de custo C que é uma função de muitas variáveis, w = w1, w2,…, então C = C(w). Pelo teorema de Taylor, a função custo pode ser aproximada perto de um ponto w por:

 

form1

Fórmula 1

 

Podemos reescrever isso de forma mais compacta:

form2

Fórmula 2

 

onde ∇C é o vetor gradiente usual e H é uma matriz conhecida como Matriz Hessiana. Suponha que nós aproximemos C descartando os termos de ordem superior representados por … acima:

 

Fórmula 3

 

Usando o cálculo, podemos mostrar que a expressão do lado direito pode ser minimizada escolhendo:

 

form4

Fórmula 4

 

Considerando que a Fórmula 3 é uma boa expressão aproximada para a função custo, então esperamos que a mudança do ponto w para form6 deva diminuir significativamente a função custo. Isso sugere um algoritmo possível para minimizar o custo:

  • Escolha um ponto de partida, w.
  • Atualize w para um novo ponto w ′ = w − H ^ − 1 ∇C, onde o Hessian H e ∇C são calculados em w.
  • Atualize w′ para um novo ponto w′′ = w′ − H′ ^ − 1 ∇′C, onde o Hessian H′ e ∇′C são calculados em w′.
    …

Na prática, a Fórmula 3 é apenas uma aproximação e é melhor dar passos menores. Fazemos isso alterando repetidamente w por uma quantidade form8 onde η é conhecido como taxa de aprendizado.

Essa abordagem para minimizar uma função de custo é conhecida como Hessian Technique ou Hessian Optimization. Existem resultados teóricos e empíricos mostrando que os métodos de Hessian convergem em um mínimo em menos etapas do que a descida de gradiente padrão. Em particular, ao incorporar informações sobre mudanças de segunda ordem na função de custo, é possível que a abordagem Hessiana evite muitas patologias que podem ocorrer na descida de gradiente. Além disso, há versões do algoritmo de retropropagação que podem ser usadas para computar o Hessian.

Se a Hessian Optimization é tão bom, por que não a estamos usando em nossas redes neurais? Infelizmente, embora tenha muitas propriedades desejáveis, tem uma propriedade muito indesejável: é muito difícil de aplicar na prática. Parte do problema é o tamanho da matriz Hessiana. Suponha que você tenha uma rede neural com 107 pesos e vieses. Em seguida, a matriz Hessiana correspondente conterá 107 × 107 = 1014 entradas. Isso é um número grande de entradas! E isso torna a computação H ^ − 1 ∇C extremamente difícil na prática. No entanto, isso não significa que não seja útil entender. De fato, há muitas variações na descida de gradiente que são inspiradas pela Hessian Optimization, mas que evitam o problema com matrizes excessivamente grandes. Vamos dar uma olhada em uma dessas técnicas, a descida do gradiente baseada em Momentum.

Momentum

Intuitivamente, a vantagem da Hessian Optimization é que ela incorpora não apenas informações sobre o gradiente, mas também informações sobre como o gradiente está mudando. A descida do gradiente baseada no Momentum baseia-se em uma intuição similar, mas evita grandes matrizes de derivadas secundárias. Para entender a técnica de Momentum, pense em nossa imagem original de descida do gradiente, na qual consideramos uma bola rolando em um vale (veja figura abaixo). Observamos que a descida do gradiente é, apesar de seu nome, apenas vagamente semelhante a uma bola caindo no fundo de um vale.

A técnica de Momentum modifica a descida do gradiente de duas maneiras que a tornam mais semelhante à imagem física. Primeiro, introduz uma noção de “velocidade” para os parâmetros que estamos tentando otimizar. O gradiente atua para alterar a velocidade, não (diretamente) a “posição”, da mesma maneira que as forças físicas alteram a velocidade, afetando apenas indiretamente a posição. Em segundo lugar, o método Momentum introduz um tipo de termo de fricção, que tende a reduzir gradualmente a velocidade.

Vamos dar uma descrição matemática mais precisa. Introduzimos variáveis de velocidade v = v1, v2,…, uma para cada variável wj correspondente. Então nós substituímos a regra de atualização de descida de gradiente w → w′ = w − η∇C por:

 

form5

 

Nessas equações, μ é um hiperparâmetro que controla a quantidade de amortecimento ou atrito no sistema. Para entender o significado das equações, é útil considerar primeiro o caso onde μ = 1, o que corresponde a nenhum atrito. Quando esse é o caso, a inspeção das equações mostra que a “força” ∇C está agora modificando a velocidade, v, e a velocidade está controlando a taxa de variação de w. Intuitivamente, nós aumentamos a velocidade adicionando repetidamente termos de gradiente a ela. Isso significa que se o gradiente estiver na (aproximadamente) mesma direção através de várias rodadas de aprendizado, poderemos desenvolver um pouco de vapor movendo-se nessa direção. Pense, por exemplo, no que acontece se estivermos nos movendo diretamente por um declive:

gradient

 

A cada passo a velocidade se torna maior no declive, então nos movemos mais e mais rapidamente para o fundo do vale. Isso pode permitir que a técnica de Momentum funcione muito mais rapidamente do que a descida de gradiente padrão. Claro, um problema é que, uma vez que chegarmos ao fundo do vale, vamos ultrapassar. Ou, se o gradiente deve mudar rapidamente, então podemos nos encontrar indo na direção errada. Essa é a razão para o hiperparâmetro µ nas equações acima.

Eu disse anteriormente que μ controla a quantidade de atrito no sistema; para ser um pouco mais preciso, você deve pensar em 1 − μ como a quantidade de atrito no sistema. Quando μ = 1, como vimos, não há atrito e a velocidade é completamente controlada pelo gradiente ∇C. Em contraste, quando μ = 0 há muito atrito, a velocidade não pode se acumular e as equações acima reduzem à equação usual para o gradiente descendente, w → w ′ = w − η∇C. Na prática, usar um valor intermediário entre 0 e 1 pode nos dar muito do benefício de ser capaz de aumentar a velocidade, mas sem causar overshooting. Podemos escolher um valor para μ usando os dados de validação retidos, da mesma maneira que selecionamos η e λ. 

Evitei nomear o hiperparâmetro μ até agora. A razão é que o nome padrão para μ é mal escolhido: é chamado de coeficiente de momentum. Isso é potencialmente confuso, já que μ não é de maneira alguma a noção de momento da física. Pelo contrário, está muito mais relacionado ao atrito. No entanto, o termo coeficiente de momentum é amplamente utilizado, por isso continuaremos a usá-lo.

Uma coisa boa sobre a técnica do Momentum é que não é preciso quase nenhum trabalho para modificar uma implementação de descida de gradiente para incorporar o Momentum. Ainda podemos usar a retropropagação para calcular os gradientes, assim como antes, e usar ideias como a amostragem de mini-lotes estocasticamente escolhidos. Desta forma, podemos obter algumas das vantagens da Hessian Optimization, usando informações sobre como o gradiente está mudando, mas sem as desvantagens e com apenas pequenas modificações no nosso código. Na prática, a técnica do Momentum é comumente usada e, muitas vezes, acelera o aprendizado.

Até o próximo capítulo!

Referências:

Deep Learning Para Aplicações de Inteligência Artificial com Python e C++

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Deep Learning Book

Capítulo 28 – Usando Early Stopping Para Definir o Número de Épocas de Treinamento

by

Ao treinar redes neurais, várias decisões precisam ser tomadas em relação às configurações (hiperparâmetros) usadas, a fim de obter um bom desempenho. Um desses hiperparâmetros é o número de épocas de treinamento: ou seja, quantas passagens completas do conjunto de dados (épocas) devem ser usadas? Se usarmos poucas épocas, poderemos ter problemas de underfitting (ou seja, não aprender tudo o que pudermos com os dados de treinamento); se usarmos muitas épocas, podemos ter o problema oposto, overfitting (“aprender demais”, ou seja, ajustar o “ruído” nos dados de treinamento, e não o sinal).

Usamos o Early Stopping (“Parada Antecipada” ou “Parada Precoce”) exatamente para tentar definir manualmente esse valor. Também pode ser considerado um tipo de método de regularização (como L1/L2 weight decay e dropout estudados anteriormente aqui no livro), pois pode impedir o overfitting da rede neural. A imagem abaixo ajuda a definir claramente o que é o Early Stopping:

 

earlystopping

 

Ao treinar uma rede neural, geralmente se está interessado em obter uma rede com desempenho ideal de generalização. No entanto, todas as arquiteturas de rede neural padrão, como o perceptron multicamada totalmente conectado, são propensas a overfitting. Enquanto a rede parece melhorar, isto é, o erro no conjunto de treinamento diminui, em algum momento durante o treinamento na verdade começa a piorar novamente, ou seja, o erro em exemplos invisíveis aumenta.

Normalmente, o erro de generalização é estimado pelo erro de validação, isto é, o erro médio em um conjunto de validação, um conjunto fixo de exemplos que não são do conjunto de treino. Existem basicamente duas maneiras de combater o overfitting: reduzindo o número de dimensões do espaço de parâmetros ou reduzindo o tamanho efetivo de cada dimensão. Técnicas para reduzir o número de parâmetros são aprendizagem construtiva gananciosa, poda ou compartilhamento de peso. Técnicas para reduzir o tamanho de cada dimensão de parâmetro são a regularização, como weight decay ou dropout, ou a Parada Precoce (Early Stopping). A parada precoce é amplamente usada porque é simples de entender e implementar e foi relatada como sendo superior aos métodos de regularização em muitos casos.

Usar Early Stopping significa que, no final de cada época, devemos calcular a precisão da classificação nos dados de validação. Quando a precisão parar de melhorar, terminamos o treinamento. Isso torna a configuração do número de épocas muito simples. Em particular, isso significa que não precisamos nos preocupar em descobrir explicitamente como o número de épocas depende dos outros hiperparâmetros, pois isso é feito automaticamente. Além disso, a Parada Antecipada também impede automaticamente o overfitting. Isto é, obviamente, uma coisa boa, embora nos estágios iniciais da experimentação possa ser útil desligar a Parada Antecipada, para que você possa ver quaisquer sinais de overfitting e usá-los para definir sua abordagem de regularização.

Para implementar a Parada Antecipada, precisamos dizer com mais precisão o que significa que a precisão da classificação parou de melhorar. Como já vimos, a precisão pode se mover um pouco, mesmo quando a tendência geral é melhorar. Se pararmos pela primeira vez, a precisão diminui, então quase certamente pararemos quando houver mais melhorias a serem feitas. Uma regra melhor é terminar se a melhor precisão de classificação não melhorar por algum tempo. Suponha, por exemplo, que estamos trabalhando com o dataset MNIST. Poderíamos optar por terminar se a precisão da classificação não melhorou durante as últimas dez épocas. Isso garante que não paremos cedo demais, em resposta à má sorte no treinamento, mas também que não estamos esperando para sempre uma melhoria que nunca acontece.

Esta regra de “parar o treinamento se não melhorar em dez épocas” é boa para a exploração inicial do MNIST. No entanto, as redes podem às vezes estabilizar-se perto de uma determinada precisão de classificação por algum tempo, apenas para começar a melhorar novamente. Se você está tentando obter um desempenho realmente bom, a regra de “parar o treinamento se não melhorar em dez épocas” pode ser muito agressiva. Nesse caso, sugerimos usar essa regra para a experimentação inicial e, gradualmente, adotar regras mais brandas, conforme entender melhor a maneira como sua rede treina: sem melhoria em vinte épocas, sem melhoria em cinquenta épocas e assim por diante. Claro, isso introduz um novo hiperparâmetro para otimizar! Na prática, no entanto, geralmente é fácil definir esse hiperparâmetro para obter bons resultados. Da mesma forma, para problemas diferentes do MNIST, a regra de não-melhoria-em-dez pode ser agressiva demais ou não ser agressiva o suficiente, dependendo dos detalhes do problema. No entanto, com um pouco de experimentação, geralmente é fácil encontrar uma boa estratégia para o Early Stopping. Isso faz parte do trabalho do Cientista de Dados ou do Engenheiro de Inteligência Artificial.

Até aqui, nós não usamos o Early Stopping em nossos experimentos MNIST. A razão é que temos feito muitas comparações entre diferentes abordagens de aprendizado. Para tais comparações, é útil usar o mesmo número de épocas em cada caso. No entanto, vale a pena modificar o network2.py para implementar o Early Stopping, e deixaremos isso como tarefa para você. Se precisar de ajuda, o Early Stopping é estudado em detalhes aqui.

Até o próximo capítulo!

Referências:

Formação Linguagem Python Para Data Science

Practical Recommendations for Gradient-Based Training of Deep Architectures

Gradient-Based Learning Applied to Document Recognition

Neural Networks & The Backpropagation Algorithm, Explained

Neural Networks and Deep Learning

Machine Learning

The Elements of Statistical Learning: Data Mining, Inference, and Prediction, Second Edition

Gradient Descent For Machine Learning

Pattern Recognition and Machine Learning

Paginação de posts

  • 1
  • 2
  • 3
  • Next

Capítulos Recentes

  • Capítulo 35 – A Matemática do Problema de Dissipação do Gradiente em Deep Learning
  • Capítulo 34 – O Problema da Dissipação do Gradiente
  • Capítulo 33 – Por que as Redes Neurais Profundas São Difíceis de Treinar?
  • Capítulo 32 – Como Uma Rede Neural Artificial Encontra a Aproximação de Uma Função
  • Capítulo 31 – As Redes Neurais Artificiais Podem Computar Qualquer Função?
  • Capítulo 30 – Variações do Stochastic Gradient Descent – Hessian Optimization e Momentum
  • Capítulo 29 – Definindo o Tamanho do Mini-Batch
  • Capítulo 28 – Usando Early Stopping Para Definir o Número de Épocas de Treinamento
  • Capítulo 27 – A Taxa de Aprendizado de Uma Rede Neural
  • Capítulo 26 – Como Escolher os Hiperparâmetros de Uma Rede Neural

Buscar

Podcast DSA

© 2025 Data Science Academy - www.datascienceacademy.com.br