Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

<p>W</p><p>BA</p><p>08</p><p>71</p><p>_V</p><p>1.</p><p>0</p><p>DEEP LEARNING</p><p>2</p><p>Rogério Ferreira</p><p>São Paulo</p><p>Platos Soluções Educacionais S.A</p><p>2021</p><p>DEEP LEARNING</p><p>1ª edição</p><p>3</p><p>2021</p><p>Platos Soluções Educacionais S.A</p><p>Alameda Santos, n° 960 – Cerqueira César</p><p>CEP: 01418-002— São Paulo — SP</p><p>Homepage: https://www.platosedu.com.br/</p><p>Diretor Presidente Platos Soluções Educacionais S.A</p><p>Paulo de Tarso Pires de Moraes</p><p>Conselho Acadêmico</p><p>Carlos Roberto Pagani Junior</p><p>Camila Turchetti Bacan Gabiatti</p><p>Camila Braga de Oliveira Higa</p><p>Giani Vendramel de Oliveira</p><p>Gislaine Denisale Ferreira</p><p>Henrique Salustiano Silva</p><p>Mariana Gerardi Mello</p><p>Nirse Ruscheinsky Breternitz</p><p>Priscila Pereira Silva</p><p>Tayra Carolina Nascimento Aleixo</p><p>Coordenador</p><p>Henrique Salustiano Silva</p><p>Revisor</p><p>Edilson José Rodrigues</p><p>Editorial</p><p>Alessandra Cristina Fahl</p><p>Beatriz Meloni Montefusco</p><p>Carolina Yaly</p><p>Mariana de Campos Barroso</p><p>Paola Andressa Machado Leal</p><p>Dados Internacionais de Catalogação na Publicação (CIP)_________________________________________________________________________________________</p><p>Silva, Rogerio Ferreira da</p><p>S586d Deep learning / Rogerio Ferreira da Silva, – São Paulo:</p><p>Platos Soluções Educacionais S.A., 2021.</p><p>44 p.</p><p>ISBN 978-65-89881-52-0</p><p>1. Deep learning. 2. Redes neurais. 3. Convolucionais.</p><p>I. Título.</p><p>CDD 005</p><p>____________________________________________________________________________________________</p><p>Evelyn Moraes – CRB 010289/O</p><p>© 2021 por Platos Soluções Educacionais S.A.</p><p>Todos os direitos reservados. Nenhuma parte desta publicação poderá ser</p><p>reproduzida ou transmitida de qualquer modo ou por qualquer outro meio,</p><p>eletrônico ou mecânico, incluindo fotocópia, gravação ou qualquer outro tipo de</p><p>sistema de armazenamento e transmissão de informação, sem prévia autorização,</p><p>por escrito, da Platos Soluções Educacionais S.A.</p><p>4</p><p>SUMÁRIO</p><p>Introdução às Redes Neurais Artificiais _______________________ 05</p><p>Treinamento de Redes Neurais Profundas __________________ 20</p><p>Redes neurais convolucionais _______________________________ 35</p><p>Redes neurais recorrentes ___________________________________ 49</p><p>DEEP LEARNING</p><p>5</p><p>Introdução às Redes Neurais</p><p>Artificiais</p><p>Autoria: Rogério Ferreira</p><p>Leitura crítica: Edilson José Rodrigues</p><p>Objetivos</p><p>• Compreender os conceitos fundamentais das Redes</p><p>Neurais Artificiais.</p><p>• Apresentar o Perceptron: modelo fundamental das</p><p>redes neurais.</p><p>• Estudar o conceito de redes neurais multicamadas.</p><p>• Descrever o funcionamento do algoritmo</p><p>backpropagation.</p><p>6</p><p>1. Introdução às Redes Neurais Artificiais</p><p>Assim como os pássaros estimularam a criação dos aviões, a natureza</p><p>foi fonte de inspiração para inúmeras invenções humanas. Nesse</p><p>sentido, parece lógico observar a arquitetura do cérebro humano em</p><p>busca de inspiração sobre como construir uma máquina inteligente.</p><p>Essa é a lógica utilizada para criação das Redes Neurais Artificiais</p><p>(RNA). Uma RNA é um modelo de aprendizado de máquina que</p><p>tenta reproduzir o funcionamento das redes de neurônios biológicos</p><p>encontradas no cérebro. Contudo, embora os aviões tenham sido</p><p>inspirados por pássaros, eles não precisam bater as asas. Da mesma</p><p>forma, as RNA se tornaram gradualmente diferentes de seus “primos”</p><p>biológicos. Alguns pesquisadores argumentam que devemos abandonar</p><p>completamente a analogia biológica, por exemplo, dizendo “unidades”</p><p>em vez de “neurônios”, para não restringir nossa criatividade a sistemas</p><p>biologicamente plausíveis (ARTASANCHEZ; JOSHI, 2020).</p><p>RNA são o conceito central de aprendizagem profunda (deep learning).</p><p>Conforme Geron (2019) elas são versáteis, poderosas, escaláveis e ideais</p><p>para lidar com tarefas de aprendizado de máquina extensas e altamente</p><p>complexas. Assim, podem classificar bilhões de imagens (como as</p><p>imagens do Google), alimentar serviços de reconhecimento de voz (como</p><p>a Siri da Apple), recomendar os melhores vídeos para assista a centenas</p><p>de milhões de usuários todos os dias (como os vídeos do YouTube)</p><p>ou aprender a derrotar o campeão mundial no jogo Go (DeepMind’s</p><p>AlphaGo).</p><p>As próximas seções descrevem os principais conceitos relacionados às</p><p>redes neurais artificiais.</p><p>7</p><p>2. Dos neurônios biológicos aos artificiais</p><p>Ao contrário do que muitas pessoas imaginam, as RNA já existem há</p><p>várias décadas: foram introduzidas pela primeira vez em 1943 pelo</p><p>neurofisiologista Warren McCulloch e o matemático Walter Pitts. Ambos</p><p>apresentaram um modelo computacional simplificado de como os</p><p>neurônios artificiais poderiam trabalhar para realizar cálculos complexos</p><p>usando lógica proposicional. Esta foi a primeira arquitetura de rede</p><p>neural. Desde então, muitas outras foram propostas. No início da</p><p>década de 1980, foram desenvolvidas novas técnicas de treinamento</p><p>para as RNA, gerando maior interesse no conexionismo – o estudo</p><p>de redes neurais. Contudo, o progresso era lento e, na década de</p><p>1990, outras técnicas poderosas de aprendizado de máquina foram</p><p>inventadas, como o algoritmo SVM (Support Vector Machines). Segundo</p><p>Geron (2019), essas técnicas pareciam oferecer melhores resultados</p><p>e fundamentos teóricos mais fortes do que as RNA, o que motivou a</p><p>suspensão do estudo desta técnica.</p><p>A partir da última década, testemunhou-se uma onda crescente de</p><p>interesse no desenvolvimento de técnicas de aprendizado de máquina</p><p>baseadas em RNA. Existem diversas razões que nos fazem acreditar que</p><p>este interesse se tornará cada vez maior, o que provocará um impacto</p><p>profundo em nossas vidas (ARTASANCHEZ; JOSHI, 2020):</p><p>• Atualmente, há uma grande quantidade de dados disponíveis</p><p>para treinar redes neurais, e elas frequentemente superam outras</p><p>técnicas de aprendizado de máquina ao lidar com problemas</p><p>grandes e complexos.</p><p>• O grande aumento no poder de processamento dos computadores</p><p>nas últimas décadas, o que tornou possível treinar grandes redes</p><p>neurais em um período razoável. Isso se deve, em parte, à lei de</p><p>Moore (o número de componentes em circuitos integrados dobrou</p><p>a cada 2 anos nos últimos 50 anos); e, também, à indústria de</p><p>8</p><p>jogos, que estimulou a produção de processadores cada vez mais</p><p>poderosos.</p><p>• Os algoritmos de treinamento de RNA foram aprimorados. Na</p><p>verdade, eles são apenas ligeiramente diferentes daqueles usados</p><p>na década de 1990, mas esses ajustes relativamente pequenos</p><p>tiveram um enorme impacto positivo.</p><p>• Algumas limitações teóricas das RNA, revelaram-se benignas na</p><p>prática. Por exemplo: muitas pessoas pensaram que algoritmos de</p><p>treinamento de RNA estavam condenados porque, provavelmente,</p><p>ficariam presos em soluções ótimas locais, mas isso é bastante</p><p>raro na prática. Quando é o caso, eles geralmente estão bastante</p><p>próximos de uma solução ótima global.</p><p>• As RNA parecem ter entrado em um círculo virtuoso de</p><p>financiamento e progresso. Produtos revolucionários baseados em</p><p>redes neurais chegam regularmente ao mercado, o que atrai cada</p><p>vez mais atenção e investimentos.</p><p>2.1 Neurônios biológicos</p><p>Antes de descrever os neurônios artificiais, você pode ver o</p><p>funcionamento de um neurônio biológico, representado na Figura 1.</p><p>Um neurônio é uma célula de aparência bastante incomum encontrada</p><p>principalmente no cérebro de animais. Ele é composto por um corpo</p><p>celular que contém o núcleo e a maioria dos componentes complexos</p><p>da célula. Possui também muitas extensões ramificadas chamadas</p><p>dendritos e uma extensão mais longa chamada axônio. O comprimento</p><p>do axônio pode ser apenas algumas vezes maior do que o corpo da</p><p>célula, ou até dezenas de milhares de vezes mais longo. Perto de sua</p><p>extremidade, o axônio se divide em muitos ramos chamados terminais</p><p>sinápticos (ou simplesmente sinapses), que estão conectados aos</p><p>dendritos ou corpos celulares de outros neurônios. Neurônios biológicos</p><p>9</p><p>produzem curtos impulsos elétricos chamados potenciais de ação (PA,</p><p>ou apenas sinais) que viajam ao longo dos axônios e fazem com que</p><p>as sinapses liberem sinais químicos chamados neurotransmissores.</p><p>Quando um neurônio recebe</p><p>estado h0. Este novo estado, por sua vez, é passado para o</p><p>mesmo neurônio recorrente junto com o próximo valor de entrada,</p><p>x(1), e o processo é repetido até a última etapa de tempo. Em seguida,</p><p>a camada apenas exibe o último valor, y49. Esse processo é executado</p><p>simultaneamente para todas as séries temporais.</p><p>Se você compilar, ajustar e avaliar este modelo por 20 épocas usando o</p><p>otimizador adam, como no exemplo anterior, você perceberá que o valor</p><p>do erro quadrático médio atinge apenas 0.014. Portanto, ele é melhor</p><p>do que a abordagem “ingênua”, mas ainda não supera um simples linear</p><p>modelo. Observe que, para cada neurônio, um modelo linear tem um</p><p>parâmetro por entrada e por intervalo de tempo, mais um termo de</p><p>viés (no modelo linear simples que usamos, isso resulta em um total de</p><p>51 parâmetros). Em contraste, para cada neurônio recorrente em um</p><p>RNN simples, há apenas um parâmetro por entrada, e por dimensão</p><p>de estado oculto, que é apenas o número de neurônios recorrentes na</p><p>camada, mais um termo de viés. Assim, nesta RNN simples, temos um</p><p>total de apenas três parâmetros.</p><p>60</p><p>Aparentemente, a RNN apresentada era simples demais para obter</p><p>um bom desempenho. Então, vamos tentar adicionar mais camadas</p><p>recorrentes. É bastante comum empilhar várias camadas de células em</p><p>uma RNN profunda, como a mostrada na Figura 6.</p><p>Figura 6 – RNN profunda (à esquerda) e sua representação em</p><p>função do tempo (à direita)</p><p>Fonte: Geron (2019).</p><p>Implementar um RNN profunda com a biblioteca tf.keras é bastante</p><p>simples: basta empilhar as camadas recorrentes. No exemplo de código-</p><p>fonte mostrado a seguir, usamos três camadas do tipo SimpleRNN.</p><p>model = keras.models.Sequential([</p><p>keras.layers.SimpleRNN(20, return_sequences=True,</p><p>input_shape=[None, 1]),</p><p>keras.layers.SimpleRNN(20, return_sequences=True),</p><p>keras.layers.SimpleRNN(1)</p><p>])</p><p>Se você compilar, ajustar e avaliar este modelo, verá que ele atinge um</p><p>erro quadrático médio de 0.003, desempenho superior ao modelo linear.</p><p>61</p><p>Observe que a última camada não é ideal, pois camadas do tipo</p><p>SimpleRNN usam a função de ativação tangente hiperbólica por</p><p>padrão, assim os valores previstos devem estar entre -1 e 1. Se você</p><p>quiser usar outra função de ativação, pode ser preferível substituir</p><p>a camada de saída por uma camada completamente conectada</p><p>(tipo Dense). Ela executa um pouco mais rápido praticamente com a</p><p>mesma precisão e nos permite escolher qualquer função de ativação</p><p>de saída que desejarmos. Se essa alteração for feita, deve-se certificar</p><p>de remover return_sequences = True da segunda (e agora última)</p><p>camada recorrente, com mostra o trecho de código-fonte a seguir:</p><p>model = keras.models.Sequential([</p><p>keras.layers.SimpleRNN(20, return_sequences=True,</p><p>input_shape=[None, 1]),</p><p>keras.layers.SimpleRNN(20),</p><p>keras.layers.Dense(1)</p><p>])</p><p>Se você treinar esse modelo, verá que ele converge mais rápido e tem</p><p>um desempenho tão bom quanto o anterior. Além disso, você pode</p><p>alterar a função de ativação de saída, se desejar.</p><p>4. Considerações finais</p><p>Nesta unidade você estudou conceitos relacionados às redes neurais</p><p>recorrentes (RNN). O princípio básico de uma RNN é que seus neurônios</p><p>recebem normalmente as entradas, produzem uma saída e a enviam</p><p>de volta para o próprio neurônio, ou seja, em cada etapa de tempo</p><p>um neurônio recorrente recebe as suas entradas, além da sua própria</p><p>saída produzida na etapa anterior. Essa característica faz com que a</p><p>RNN mantenha armazenado algum tipo de estado em intervalos de</p><p>62</p><p>tempo diferentes, o que é chamado de célula de memória. Um neurônio</p><p>recorrente é uma célula básica capaz de aprender alguns padrões</p><p>curtos. Por fim, você estudou como definir, implementar e treinar tanto</p><p>uma RNN simples como uma profunda. A partir do conhecimento destes</p><p>conceitos básicos, você estará apto para estudar características mais</p><p>completas das redes neurais recorrentes.</p><p>Referências</p><p>ARTASANCHEZ, Alberto; JOSHI, Prateek. Artifcial Intelligence with Python: your</p><p>complete guide to building intelligent apps using Python 3.x and Tensorflow 2. 2. ed.</p><p>Birmingham: Packt Publishing, 2020.</p><p>GERON, Aurélien. Hands-on machine learning with Scikit-Learn, Keras, and</p><p>TensorFlow: Concepts, tools, and techniques to build intelligent systems. 2. ed.</p><p>Sebastopol: O’Reilly Media, 2019.</p><p>KERAS. Keras: Deep learning for humans. 2021. Disponível em: https://keras.io/.</p><p>Acesso em: 6 mar. 2021.</p><p>63</p><p>BONS ESTUDOS!</p><p>Sumário</p><p>Introdução às Redes Neurais Artificiais</p><p>Objetivos</p><p>1. Introdução às Redes Neurais Artificiais</p><p>2. Dos neurônios biológicos aos artificiais</p><p>3. O Perceptron</p><p>4. Perceptron multicamadas e o algoritmo backpropagation (retro-propagação)</p><p>5. Considerações Finais</p><p>Referências</p><p>Treinamento de Redes Neurais Profundas</p><p>Objetivos</p><p>1. A atividade de treinamento em redes neurais profundas</p><p>Referências</p><p>Redes neurais convolucionais.</p><p>Objetivos</p><p>1. Introdução</p><p>2. A arquitetura do córtex visual</p><p>3. Camadas convolucionais</p><p>4. Camadas Pooling</p><p>5. Arquiteturas de redes neurais convolucionais</p><p>6. Considerações Finais</p><p>Referências</p><p>Redes neurais recorrentes.</p><p>Objetivos</p><p>1. Introdução</p><p>2. As redes neurais e camadas recorrentes</p><p>3. Previsão de séries temporais</p><p>4. Considerações finais</p><p>Referências</p><p>uma quantidade suficiente desses</p><p>neurotransmissores em alguns milissegundos, ele dispara seus próprios</p><p>impulsos elétricos. Na verdade, como aponta Geron (2019), isso também</p><p>depende das características dos neurotransmissores, já que alguns deles</p><p>inibem o disparo do neurônio.</p><p>Individualmente, os neurônios biológicos parecem se comportar de</p><p>uma forma bastante simples. Para realizar tarefas complexas, eles são</p><p>organizados em uma rede de bilhões de neurônios, em que cada célula</p><p>normalmente está conectada a milhares de outras. Para Geron (2019),</p><p>a arquitetura das redes neurais biológicas ainda é objeto de inúmeras</p><p>pesquisas. Contudo, algumas partes do cérebro foram mapeadas, e</p><p>parece que os neurônios são frequentemente organizados em camadas</p><p>consecutivas, especialmente no córtex cerebral (camada externa do</p><p>cérebro), conforme mostrado na Figura 2.</p><p>Figura 1 – Representação de um neurônio biológico</p><p>Fonte: Vitalii Dumma/iStock.com.</p><p>10</p><p>Figura 2 – Múltiplas camadas em uma rede neural biológica (córtex</p><p>cerebral)</p><p>Fonte: Geron (2019)</p><p>2.2 Operações lógicas com neurônios</p><p>Warren McCulloch e Walter Pitts propuseram um modelo muito simples</p><p>para representar o neurônio biológico, que mais tarde ficou conhecido</p><p>como neurônio artificial: ele tem uma ou mais entradas binárias (zero ou</p><p>um) e uma saída também binária. O neurônio artificial, ativa sua saída</p><p>quando mais de um certo número de suas entradas estão ativas. Eles</p><p>mostraram que, mesmo com um modelo bastante simples, é possível</p><p>construir uma rede de neurônios artificiais que implementa qualquer</p><p>tipo de operação lógica. Para entender como essa rede funciona,</p><p>observe as RNA que realizam várias operações lógicas na Figura 3.</p><p>Considere, segundo Geron (2019), que um neurônio é ativado quando</p><p>pelo menos duas de suas entradas estão ativas.</p><p>11</p><p>Figura 3 – Redes neurais executando diferentes operações lógicas</p><p>Fonte: Geron (2019).</p><p>Observe a seguir a lógica de funcionamento das redes neurais</p><p>apresentadas na Figura 3:</p><p>• A primeira rede à esquerda realiza a operação de identidade: se o</p><p>neurônio A for ativado, o neurônio C também será ativado (uma</p><p>vez que recebe dois sinais de entrada do neurônio A); mas se o</p><p>neurônio A está desativado, o neurônio C também será desativado.</p><p>• A segunda rede realiza a operação lógica E: o neurônio C é ativado</p><p>apenas quando os neurônios A e B são ativados (um único sinal de</p><p>entrada não é suficiente para ativar o neurônio C).</p><p>• A terceira rede realiza a operação lógica OU: o neurônio C é</p><p>ativado se o neurônio A ou o neurônio B for ativado (ou ambos).</p><p>• Finalmente, se supormos que uma conexão de entrada pode inibir</p><p>a atividade do neurônio, a quarta rede realiza uma operação lógica</p><p>um pouco mais complexa: o neurônio C é ativado apenas se o</p><p>neurônio A estiver ativo e o neurônio B estiver desativado. Se o</p><p>neurônio A está ativo o tempo todo, você obtém um NÃO lógico.</p><p>Como podemos perceber, as redes neurais podem ser combinadas das</p><p>mais diferentes formas para calcular expressões lógicas complexas.</p><p>12</p><p>3. O Perceptron</p><p>O Perceptron é uma das arquiteturas de RNA mais simples que existem.</p><p>Ela foi inventada em 1957 por Frank Rosenblatt, e foi baseada em um</p><p>neurônio artificial ligeiramente diferente (como pode ser visto na Figura</p><p>4), chamado de unidade lógica de limiar (threshold logic unit–TLU). As</p><p>entradas e saídas são números (em vez de valores binários) e cada</p><p>conexão de entrada está associada a um peso. O TLU calcula uma soma</p><p>ponderada de suas entradas (z = w1 x1 + w2 x2 + ... + wn xn = xTw) e, em</p><p>seguida, aplica uma função degrau (step) a essa soma que produz o</p><p>resultado: hw(x) = step(z), em que z = xTw.</p><p>Figura 4 – TLU: neurônio artificial que calcula uma soma ponderada</p><p>de suas entradas e, em seguida, aplica a função degrau</p><p>Fonte: Geron (2019).</p><p>A função degrau mais comum usada em Perceptrons, conforme Albon</p><p>(2018), é a função heaviside; em algumas arquiteturas, a função signal é</p><p>usada. Ambas são mostradas a seguir:</p><p>Um único TLU pode ser usado para realizar classificação binária</p><p>simples. Ele calcula uma combinação linear das entradas e, se o</p><p>Saída:</p><p>Função degrau:</p><p>Soma ponderada:</p><p>Pesos</p><p>Entradas</p><p>13</p><p>resultado exceder um limite, gera a classe positiva. Caso contrário,</p><p>ele gera a classe negativa, como acontece em uma regressão logística</p><p>ou classificador que utiliza o algoritmo linear SVM. Você poderia, por</p><p>exemplo, usar um único TLU para classificar as flores de um conjunto de</p><p>dados como pertencentes ou não a uma determinada espécie. Treinar a</p><p>rede neural neste caso, significa encontrar os valores adequados para os</p><p>pesos w1, w2 e w3, de acordo com os valores de entrada.</p><p>Um Perceptron é formado simplesmente por uma única camada de TLU,</p><p>sendo que cada um deles está conectado a todas as entradas. Quando</p><p>os neurônios em uma camada estão conectados a todos os neurônios</p><p>da camada anterior (ou seja, os neurônios de entrada), a camada é</p><p>chamada de totalmente conectada ou densa. As entradas do Perceptron</p><p>são alimentadas por neurônios especiais chamados neurônios de</p><p>entrada: eles se limitam a replicar qualquer valor que recebem. Além</p><p>disso, um recurso extra geralmente é adicionado, sendo representado</p><p>por um tipo especial de neurônio chamado de viés (bias), que sempre</p><p>possui o valor 1. A Figura 5 representa um Perceptron com duas entradas</p><p>e três saídas. Ele pode classificar instâncias simultaneamente em três</p><p>classes binárias diferentes, o que o torna um classificador de múltiplas</p><p>saídas, segundo Geron (2019).</p><p>Figura 5 – Arquitetura de um Perceptron com dois neurônios de</p><p>entrada, um neurônio do tipo viés e três neurônios de saída</p><p>Fonte: Geron (2019).</p><p>14</p><p>Uma arquitetura de redes neurais com poucos neurônios tem baixo</p><p>potencial de resolução de problemas. Para realizar tarefas complexas, é</p><p>necessário associar diversos neurônios em uma arquitetura baseada em</p><p>camadas, como será discutido na próxima seção.</p><p>4. Perceptron multicamadas e o algoritmo</p><p>backpropagation (retro-propagação)</p><p>Um Perceptron multicamadas (Multilayer Perceptron – MLP) é composto</p><p>por uma camada de entrada, uma ou mais camadas intermediárias</p><p>de neurônios, chamadas de camadas ocultas, e uma camada final de</p><p>neurônios, chamada de camada de saída. As camadas próximas à de</p><p>entrada são geralmente chamadas de camadas inferiores e as próximas</p><p>às saídas são chamadas de camadas superiores. Cada uma delas,</p><p>exceto a camada de saída, inclui um neurônio chamado de viés (bias). A</p><p>Figura 6 apresenta a arquitetura de um MLP contendo duas entradas,</p><p>uma camada oculta de quatro neurônios e três neurônios de saída.</p><p>Os neurônios de viés (representados pelo círculo com o número 1)</p><p>são mostrados nesta arquitetura, contudo, é comum que eles estejam</p><p>ocultos.</p><p>Quando uma RNA contém mais de duas camadas ocultas de neurônios,</p><p>ela é chamada de rede neural profunda (RNP). A aprendizagem profunda</p><p>estuda as RNP e, de maneira geral, são arquiteturas projetadas para</p><p>solucionar problemas extremamente complexos.</p><p>Por muitos anos, os pesquisadores da área de Inteligência Artificial</p><p>trabalharam para encontrar uma maneira eficiente de treinar MLP,</p><p>sem sucesso. Contudo, em 1986, David Rumelhart, Geoffrey Hinton e</p><p>Ronald Williams publicaram um artigo inovador (RUMELHART; HINTON;</p><p>WILLIAMS, 1985) que introduziu o algoritmo de treinamento chamado</p><p>backpropagation (retro-propagação), que continua sendo usado até</p><p>15</p><p>hoje. Como descreve Geron (2019), em apenas duas passagens pela</p><p>arquitetura da rede (uma para a frente e outra uma para trás), o</p><p>algoritmo backpropagation é capaz de calcular o coeficiente de erro da</p><p>rede neural em relação a todos os parâmetros do modelo. Em outras</p><p>palavras, ele pode descobrir como cada peso entre as conexões deve ser</p><p>ajustado para reduzir o valor do erro.</p><p>A seguir são descritos os passos do algoritmo backpropagation com mais</p><p>detalhes:</p><p>Figura 6 – Arquitetura de um MLP com três camadas</p><p>Fonte: Geron (2019).</p><p>• O algoritmo trabalha com um mini-lote (mini-batch) dos dados</p><p>de</p><p>treinamento por vez, contendo, por exemplo, 32 instâncias cada;</p><p>assim, ele processa todo o conjunto de treinamento diversas vezes.</p><p>Cada vez que o algoritmo processa todo o conjunto de dados dá-se</p><p>o nome de época.</p><p>• Os dados de cada mini-lote são enviados pela camada de entrada</p><p>da rede para a primeira camada oculta. O algoritmo, então, calcula</p><p>a saída de todos os neurônios; o resultado é enviado para a</p><p>próxima camada, e assim sucessivamente, até obtermos a saída da</p><p>última camada da arquitetura. Este processo é chamado de feed-</p><p>forward (passe para frente).</p><p>Camada de</p><p>saída</p><p>Camada</p><p>escondida</p><p>Camada de</p><p>entrada</p><p>16</p><p>• Em seguida, o algoritmo calcula o erro de saída da rede: ele usa</p><p>uma função de custo (ou função de perda) que compara a saída</p><p>desejada e a saída real do conjunto de dados de treinamento,</p><p>retornando, assim, o valor mensurado do erro.</p><p>• Na sequência, o algoritmo calcula o quanto cada conexão de</p><p>saída contribuiu para o valor do erro mensurado. Isso é feito</p><p>de forma analítica aplicando a regra da cadeia (uma das teorias</p><p>fundamentais do cálculo), o que torna essa etapa rápida e precisa.</p><p>• A partir da camada de saída, o algoritmo mensura o quanto a</p><p>camada imediatamente inferior contribui para o valor do erro,</p><p>e executa esse processamento “para trás” até que o algoritmo</p><p>alcance a camada de entrada. Conforme explicado anteriormente,</p><p>esta passagem reversa mede de forma eficiente o erro em todos</p><p>os pesos de conexão na rede neural, propagando esse erro para</p><p>trás (retro-propagação), o que justamente define o nome do</p><p>algoritmo.</p><p>• Por fim, o algoritmo executa uma técnica chamada Descida do</p><p>Gradiente ou Gradiente Descendente (Gradient Descent) para</p><p>ajustar todos os pesos de conexão na rede neural, usando os</p><p>valores dos erros que acabou de calcular.</p><p>Este algoritmo backpropagation é tão importante que vale a pena</p><p>resumir o seu funcionamento: para cada instância de treinamento,</p><p>o algoritmo primeiro faz sua previsão e calcula o valor do erro (feed-</p><p>forward); em seguida, concentra-se na camada imediatamente anterior</p><p>e calcula a contribuição de cada conexão para o erro (backpropagation);</p><p>finalmente, ajusta os pesos das conexões para reduzir o valor do erro</p><p>(descida do gradiente).</p><p>Para que o algoritmo funcione corretamente, seus autores fizeram</p><p>uma mudança fundamental na arquitetura do MLP: eles substituíram a</p><p>função degrau pela função logística (sigmóide): . Isso</p><p>17</p><p>foi essencial porque a função degrau contém apenas segmentos planos,</p><p>assim, não há um gradiente para processar, porque a técnica da descida</p><p>do gradiente não pode se mover em uma superfície plana. Por sua vez,</p><p>a função logística tem uma derivada diferente de zero bem definida,</p><p>permitindo que a descida do gradiente faça progressos ao longo das</p><p>etapas. Na verdade, o algoritmo backpropagation funciona bem com</p><p>muitas outras funções de ativação, não apenas a função logística. Outras</p><p>opções bastante populares são:</p><p>• A função da tangente hiperbólica (hyperbolic tangent function):</p><p>• A função de ativação linear retificada (Rectifed Linear Unit function –</p><p>ReLU):</p><p>O gráfico das funções degrau, sigmoide, tangente hiperbólica e ReLU,</p><p>além das suas respectivas derivadas, são mostradas na Figura 7.</p><p>Figura 7 – Funções de ativação e suas derivadas.</p><p>Fonte: Geron (2019).</p><p>18</p><p>5. Considerações Finais</p><p>Nessa aula, você pode conhecer os conceitos básicos das redes neurais</p><p>artificiais (RNA). As RNA, assim como outras técnicas usadas em</p><p>Inteligência Artificial (IA), são modelos computacionais bioinspirados,</p><p>ou seja, foram criadas levando em consideração o funcionamento do</p><p>cérebro humano. Uma das premissas fundamentais da IA é construir</p><p>sistemas que possam realizar tarefas que normalmente exigiriam</p><p>inteligência humana. É inegável que o nosso cérebro possui incrível</p><p>capacidade de aprender novos conceitos. Com base nessa premissa,</p><p>as RNA foram projetadas para simular o processo de aprendizagem</p><p>do cérebro humano. No início da aula você viu a representação de um</p><p>neurônio biológico, e como o seu funcionamento inspirou a criação do</p><p>Perceptron, que implementa o modelo de RNA mais simples. Contudo,</p><p>uma arquitetura de rede neural com poucos Perceptrons não é capaz</p><p>de solucionar problemas complexos. Da mesma forma que o nosso</p><p>cérebro é organizado em camadas de bilhões de neurônios, as redes</p><p>neurais precisam ser organizadas em camadas de entrada, camadas</p><p>intermediárias (ou ocultas) e camadas de saída a fim de aumentar o</p><p>seu poder de processamento. Neste contexto, surge o conceito de rede</p><p>neural profunda e aprendizagem profunda (deep learning), quando uma</p><p>arquitetura de RNA possui mais de duas camadas profundas. Por fim,</p><p>você estudou, também, o algoritmo backpropagation, utilizado para</p><p>realizar o treinamento das redes neurais, com base na contribuição</p><p>que cada camada da rede possui para o cálculo do erro na camada</p><p>de saída. A partir dos conceitos básicos apresentados, você poderá</p><p>compreender os recursos mais avançados desta técnica essencial para a</p><p>implementação de sistemas baseados em Inteligência Artificial.</p><p>19</p><p>Referências</p><p>ALBON, Chris. Machine Learning with Python Cookbook: Practical solutions from</p><p>preprocessing to deep learning. Sebastopol: O’Reilly Media, 2018.</p><p>ARTASANCHEZ, Alberto; JOSHI, Prateek. Artifcial Intelligence with Python: your</p><p>complete guide to building intelligent apps using Python 3.x and Tensorflow 2. 2. ed.</p><p>Birmingham: Packt Publishing, 2020.</p><p>GERON, Aurélien. Hands-on machine learning with Scikit-Learn, Keras, and</p><p>TensorFlow: Concepts, tools, and techniques to build intelligent systems. 2. ed.</p><p>Sebastopol: O’Reilly Media, 2019.</p><p>RUMELHART, David; HINTON, Geoffrey; WILLIAMS, Ronald. Learning internal</p><p>representations by error propagation. San Diego, 1985. Disponível em: https://</p><p>apps.dtic.mil/sti/citations/ADA164453. Acesso em: 2 mar. 2021.</p><p>20</p><p>Treinamento de Redes Neurais</p><p>Profundas</p><p>Autoria: Rogério Ferreira</p><p>Leitura crítica: Edilson José Rodrigues</p><p>Objetivos</p><p>• Discutir técnicas que podem ser aplicadas às</p><p>redes neurais profundas para otimizar a tarefa de</p><p>treinamento.</p><p>• Estudar o conceito de transferência do aprendizado.</p><p>• Apresentar técnicas de regularização que podem</p><p>aprimorar a acurácia das redes neurais profundas.</p><p>21</p><p>1. A atividade de treinamento em redes</p><p>neurais profundas</p><p>Redes Neurais Profundas (RNP) podem solucionar problemas</p><p>extremamente complexos, por exemplo, detectar centenas de objetos</p><p>em imagens de alta resolução. Para tarefas como essa, pode ser</p><p>necessário treinar uma rede neural bastante profunda, com dez ou</p><p>mais camadas, cada uma contendo centenas de neurônios, ligados por</p><p>centenas de milhares de conexões. Entre os problemas que podemos</p><p>encontrar durante o treinamento de grandes RNP, segundo Geron</p><p>(2019), destacam-se:</p><p>• Você pode não ter dados de treinamento suficientes para uma</p><p>rede tão grande, ou rotular um grande conjunto de dados com</p><p>suas respectivas classes pode ser uma tarefa muito custosa, em</p><p>termos de tempo.</p><p>• A atividade de treinamento pode ser extremamente lenta.</p><p>• Um modelo com milhões de parâmetros (conexões entre os</p><p>neurônios) corre o risco de sofrer sobreajuste (overfitting) durante</p><p>a atividade de treinamento, especialmente se não houver</p><p>exemplos de dados suficientes, ou se houver ruído (dados</p><p>inconsistentes) entre eles.</p><p>Nas próximas seções, examinaremos cada um desses problemas e</p><p>estudaremos técnicas para solucioná-los.</p><p>1.1 Reuso de camadas pré-treinadas e transferência do</p><p>aprendizado</p><p>Geralmente, não é uma boa ideia treinar uma grande RNP “do zero”. Em</p><p>vez disso, você pode buscar uma rede neural já existente que realize</p><p>uma tarefa semelhante à que precisa ser resolvida e, em seguida,</p><p>22</p><p>reutilizar as camadas inferiores dessa rede. Essa técnica é chamada</p><p>de transferência de aprendizado. Ela vai acelerar consideravelmente</p><p>a atividade de treinamento, além de requerer uma quantidade muito</p><p>menor de dados. Suponha que você tenha acesso a uma rede neural</p><p>profunda que foi treinada para classificar</p><p>imagens em 100 categorias</p><p>diferentes, incluindo animais, plantas, veículos e objetos do dia a</p><p>dia. Agora, você deseja treinar uma outra rede para classificar tipos</p><p>específicos de veículos. Essas duas tarefas são muito semelhantes,</p><p>portanto, você pode tentar reutilizar partes da primeira RNP, como</p><p>mostrado na Figura 1.</p><p>Figura 1 – Exemplo genérico de reuso de camadas pré-treinadas</p><p>Fonte: Geron (2019).</p><p>A camada de saída da rede original geralmente precisa ser substituída,</p><p>pois não será útil pelo fato de não ter o número de saídas da nova</p><p>tarefa. Da mesma forma, as camadas ocultas superiores do modelo</p><p>original têm alta probabilidade de ser menos úteis que as camadas</p><p>inferiores, uma vez que os atributos de alto nível para a nova tarefa</p><p>podem diferir de forma significativa daqueles que foram realmente úteis</p><p>para a tarefa original.</p><p>23</p><p>Quanto mais semelhantes são as tarefas, maior é o número de</p><p>camadas que você pode reutilizar (começando com as inferiores). Se as</p><p>tarefas são muito parecidas, tente manter todas as camadas ocultas,</p><p>substituindo apenas a de saída, e treine o seu modelo para ver como ele</p><p>se comporta. Se o desempenho não for o desejado, tente descartar uma</p><p>ou duas das camadas ocultas superiores para permitir que as demais</p><p>sejam ajustadas pelo algoritmo de retro-propagação; em seguida,</p><p>confira se o desempenho melhorou. Quanto mais dados de treinamento</p><p>estiverem disponíveis, mais camadas ocultas poderão ser substituídas.</p><p>Uma alternativa válida é reduzir a taxa de aprendizado ao descartar</p><p>ou substituir camadas ocultas. Isso evitará que os pesos já ajustados</p><p>sejam desconfigurados. Se ainda assim o desempenho da RNP não for</p><p>satisfatório e você tiver poucos dados de treinamento, tente descartar</p><p>mais camadas ocultas superiores, mantendo as camadas inferiores, e</p><p>treine novamente a rede. Você pode iterar esse processo até encontrar o</p><p>número ideal de camadas para reutilizar. Se você tiver muitos dados de</p><p>treinamento, pode tentar adicionar novas camadas ocultas.</p><p>Vamos analisar um exemplo de transferência de aprendizado utilizando</p><p>a biblioteca Keras (KERAS, 2021) e o conjunto de dados MNIST (MNIST,</p><p>2021). Suponha que o conjunto de dados MNIST tenha apenas oito</p><p>classes – por exemplo, todas as dez classes existentes, exceto sandália</p><p>(sandal) e camisa (shirt). Alguém construiu e treinou um modelo de</p><p>RNP com a biblioteca Keras nesse conjunto de dados, obtendo um</p><p>desempenho razoavelmente bom (mais de 90% de acurácia). Vamos</p><p>chamar este de modelo A. Agora você deseja realizar uma tarefa</p><p>diferente: você tem imagens de sandálias e camisas e deseja treinar</p><p>um classificador binário (classe positiva representa a camisa, e classe</p><p>negativa representa a sandália). Considere que seu conjunto de dados</p><p>é pequeno, pois você tem apenas 200 imagens rotuladas com suas</p><p>respectivas classes. Quando você treina um novo modelo para esta</p><p>tarefa (vamos chamá-lo de modelo B) com a mesma arquitetura do</p><p>modelo A, ele também tem um desempenho razoavelmente bom</p><p>24</p><p>(97,2% de acurácia). Mas, como essa é uma tarefa menos complexa, pois</p><p>existem apenas duas classes, você esperava um desempenho melhor.</p><p>Intuitivamente, você percebe que sua tarefa é bastante semelhante a</p><p>que gerou o modelo A, então, talvez a transferência de aprendizado</p><p>possa auxiliar neste processo. A primeira etapa é criar um modelo com</p><p>base nas camadas do modelo A. Vamos reutilizar todas as suas camadas,</p><p>exceto a camada de saída. Isso é feito no trecho de código-fonte</p><p>mostrado a seguir.</p><p>model_A = keras.models.load_model(“my_model_A.h5”)</p><p>model_B_on_A = keras.models.Sequential(model_A.layers[:-1])</p><p>model_B_on_A.add(keras.layers.Dense(1, activation=”sigmoid”))</p><p>Observe que model_A e model_B_on_A compartilham algumas</p><p>camadas. Assim, quando você treinar o modelo model_B_on_A,</p><p>isso também afetará o modelo model_A. Caso queira evitar esse</p><p>comportamento, você precisa clonar a arquitetura do modelo A com</p><p>o método clone_model() antes de reutilizar suas camadas. Ainda é</p><p>necessário copiar os pesos do modelo A, como mostra o código-fonte a</p><p>seguir.</p><p>model_A_clone = keras.models.clone_model(model_A)</p><p>model_A_clone.set_weights(model_A.get_weights())</p><p>Agora é possível treinar o modelo model_B_on_A para a tarefa B.</p><p>Porém, como a nova camada de saída foi inicializada aleatoriamente,</p><p>provavelmente ela irá gerar altas taxas de erro, pelo menos durante</p><p>as primeiras épocas da atividade de treinamento. Para evitar esse</p><p>comportamento, uma possível abordagem é desativar as camadas</p><p>reutilizadas durante as primeiras épocas, dando à nova camada um</p><p>certo tempo para aprender e calibrar seus pesos. Para isso, é necessário</p><p>alterar o atributo trainable de cada camada para o valor False e</p><p>compilar o modelo, como mostrado no código-fonte a seguir:</p><p>25</p><p>for layer in model_B_on_A.layers[:-1]:</p><p>layer.trainable = False</p><p>model_B_on_A.compile(loss=”binary_crossentropy”,</p><p>optimizer=”sgd”,</p><p>metrics=[“accuracy”])</p><p>Agora você pode treinar o modelo por algumas épocas, e na sequência</p><p>reativar as camadas reutilizadas (o que requer a compilação do modelo</p><p>novamente) e continuar treinando para ajustar as camadas para a</p><p>tarefa B. Depois de reativar as camadas reutilizadas, uma boa estratégia</p><p>é reduzir a taxa de aprendizado, mais uma vez para evitar danos aos</p><p>pesos reutilizados, como você pode ver no código-fonte mostrado a</p><p>seguir:</p><p>history = model_B_on_A.fit(X_train_B,</p><p>y_train_B,</p><p>epochs = 4,</p><p>validation_data=(X_valid_B,</p><p>y_valid_B))</p><p>for layer in model_B_on_A.layers[:-1]:</p><p>layer.trainable = True</p><p>optimizer = keras.optimizers.SGD(lr = 1e-4) #padrão é 1e-2</p><p>model_B_on_A.compile(loss = ”binary_crossentropy”,</p><p>26</p><p>optimizer=optimizer,</p><p>metrics=[ “accuracy” ])</p><p>history = model_B_on_A.fit(X_train_B,</p><p>y_train_B,</p><p>epochs = 16,</p><p>validation_data=(X_valid_B, y_valid_B))</p><p>Ao final desta configuração, qual será o resultado? A acurácia da</p><p>atividade de teste deste modelo é de 99,25%, o que significa que a</p><p>aprendizagem por transferência reduziu a taxa de erro de 2,8% para</p><p>quase 0,7%. Esses bons resultados são fruto de diferentes configurações</p><p>de RNP que foram testadas, até encontrar uma que apresentasse</p><p>melhoria. A aprendizagem por transferência não funciona muito bem</p><p>com redes pequenas e densas, presumivelmente porque as pequenas</p><p>aprendem poucos padrões, e redes densas aprendem padrões muito</p><p>específicos que provavelmente não serão úteis em outras tarefas. A</p><p>aprendizagem por transferência, funciona melhor com redes neurais</p><p>profundas que tendem a aprender com atributos que possuem</p><p>comportamento mais geral, especialmente nas camadas inferiores.</p><p>1.2 Pré-treinamento não supervisionado</p><p>Suponha que você precise lidar com uma tarefa complexa, para a qual</p><p>existem poucos dados de treinamento. Além disso, você não possui um</p><p>modelo devidamente treinado em uma tarefa semelhante. Neste caso,</p><p>você deve tentar encontrar mais dados de treinamento. Muitas vezes</p><p>é relativamente fácil reunir tais dados, contudo, rotulá-los com suas</p><p>respectivas classes é uma tarefa complexa. Caso seja possível reunir</p><p>uma grande quantidade de dados de treinamento não rotulados, você</p><p>pode usá-los para treinar um modelo não supervisionado, por meio da</p><p>técnica de pré-treinamento não supervisionado. A Figura 2 representa</p><p>27</p><p>um resumo genérico desta técnica: um modelo é treinado com os dados</p><p>não rotulados usando uma técnica de aprendizado não supervisionado</p><p>e, em seguida, é ajustado para a tarefa final utilizando os dados</p><p>rotulados e uma técnica supervisionada; a parte não supervisionada</p><p>pode treinar uma camada por vez, conforme mostrado na Figura 2, ou</p><p>pode treinar diretamente o modelo completo.</p><p>Figura 2 – Exemplo genérico de pré-treinamento não supervisionado</p><p>Fonte: Geron (2019).</p><p>Em resumo, o pré-treinamento não supervisionado é uma boa opção</p><p>quando você tem uma tarefa complexa para resolver, nenhum modelo</p><p>semelhante para reutilizar e poucos dados de treinamento rotulados,</p><p>mas muitos dados de treinamento não rotulados.</p><p>28</p><p>1.3 Pré-treinamento</p><p>em uma tarefa auxiliar</p><p>Caso você não tenha muitos dados de treinamento rotulados, outra</p><p>opção é treinar uma primeira rede neural em uma tarefa auxiliar para</p><p>a qual você possa obter ou gerar facilmente dados de treinamento</p><p>rotulados e, em seguida, reutilizar as camadas inferiores dessa rede</p><p>para sua tarefa real. As camadas inferiores da primeira rede neural</p><p>irão detectar o comportamento de atributos que provavelmente serão</p><p>reutilizados pela segunda rede.</p><p>Por exemplo, se você deseja implementar um sistema de</p><p>reconhecimento facial, provavelmente terá apenas algumas fotos</p><p>de cada indivíduo, o que não será suficiente para treinar um bom</p><p>classificador. Reunir centenas de fotos de cada pessoa não seria prático.</p><p>Porém, você poderia reunir imagens aleatórias de diversas pessoas</p><p>e treinar uma primeira rede neural para detectar se duas imagens</p><p>diferentes apresentam ou não a mesma pessoa. Essa rede executaria</p><p>bem o papel de detectar rostos, portanto, reutilizar suas camadas</p><p>inferiores permitiria que você treinasse um bom classificador para</p><p>reconhecimento facial mesmo com poucos dados de treinamento.</p><p>Para aplicações de processamento de linguagem natural, você pode</p><p>baixar um corpus com milhões de documentos de texto e gerar</p><p>automaticamente dados rotulados a partir deles. Por exemplo, você</p><p>pode retirar, aleatoriamente, algumas palavras e treinar um modelo</p><p>para prever quais são as palavras faltantes. Se você conseguir treinar um</p><p>modelo para atingir um bom desempenho nesta tarefa, ele conhecerá</p><p>a linguagem suficientemente bem para ser reutilizado na sua tarefa</p><p>real. De forma geral, a atividade de gerar automaticamente o rótulo das</p><p>classes a partir dos próprios dados e, em seguida, treinar um modelo</p><p>no conjunto de treinamento “rotulado” usando técnicas supervisionadas</p><p>chama-se aprendizado auto-supervisionado (ARTASANCHEZ; JOSHI,</p><p>2020).</p><p>29</p><p>1.4 Evitando sobreajuste por meio de regularização</p><p>Redes neurais profundas normalmente têm dezenas de milhares ou até</p><p>milhões de parâmetros. Isso oferece às redes uma grande liberdade</p><p>ao processar conjuntos de dados complexos. Contudo, essa grande</p><p>flexibilidade também torna a arquitetura da rede propensa a sofrer</p><p>sobreajuste (overfitting) em relação ao conjunto de treinamento. Para</p><p>evitar esse comportamento, apontado por Geron (2010), precisamos</p><p>usar técnicas de regularização. Regularizar um modelo significa restringi-</p><p>lo. Por exemplo, considerando um modelo de regressão, quanto menos</p><p>graus de liberdade ele tiver, menor será sua probabilidade de sofrer</p><p>sobreajuste.</p><p>Uma das mais populares técnicas de regularização para redes neurais</p><p>profundas é chamada de Dropout. Ela demonstrou ser muito efetiva,</p><p>mesmo sendo um algoritmo bastante simples: na etapa de treinamento,</p><p>cada neurônio (incluindo os neurônios de entrada, mas sempre</p><p>excluindo os neurônios de saída) possui uma probabilidade p de ser</p><p>temporariamente “descartado”; isso significa que ele será totalmente</p><p>ignorado durante a etapa, mas pode ser reativado na próxima, como</p><p>pode ser visualizado na Figura 3. O hiperparâmetro p é chamado de taxa</p><p>de dropout e normalmente é definido em um valor entre 10% e 50%. Ao</p><p>final do treinamento, os neurônios deixam de ser “descartados”.</p><p>30</p><p>Figura 3 – Exemplo de regularização com a técnica dropout</p><p>Fonte: Geron (2019).</p><p>Apesar da sua simplicidade, a técnica de regularização dropout costuma</p><p>funcionar muito bem. Faça uma analogia e relacione essa técnica com</p><p>o seguinte contexto: uma empresa teria um desempenho melhor se</p><p>seus funcionários fossem instruídos a jogar “cara ou coroa” todas as</p><p>manhãs para decidir se iriam ou não trabalhar? A resposta é: talvez</p><p>sim! A empresa seria obrigada a adaptar sua organização; não poderia</p><p>depender de uma única pessoa para operar a máquina de café ou</p><p>realizar qualquer outra tarefa crítica, de modo que essa tarefa teria</p><p>que ser revezada por várias pessoas. Os funcionários teriam que</p><p>aprender a cooperar com muitos de seus colegas de trabalho, não</p><p>apenas com um pequeno grupo. A empresa se tornaria muito mais</p><p>resiliente. Se um funcionário se demitisse, isso não teria um grande</p><p>impacto na organização. Apesar de não ser evidente que essa ideia</p><p>realmente funcione para as empresas, ela certamente funciona para as</p><p>redes neurais. Neurônios treinados com a técnica dropout não podem</p><p>coadaptar-se aos seus vizinhos; eles precisam contribuir para um bom</p><p>desempenho da rede independentemente das unidades às quais estão</p><p>conectados. Eles também não podem depender excessivamente de</p><p>apenas alguns neurônios de entrada. Nesse sentido, tornam-se menos</p><p>31</p><p>sensíveis a pequenas mudanças nas entradas. Ao final do processo, você</p><p>obtém uma rede mais robusta e que generaliza com mais precisão.</p><p>Outra maneira de entender o poder da técnica dropout é perceber que</p><p>uma rede neural única é gerada em cada etapa do treinamento. Uma</p><p>vez que cada neurônio pode estar presente ou ausente, há um total de</p><p>2N redes possíveis, onde N é o número total de neurônios que podem</p><p>ser descartados. Este é um número tão grande que é virtualmente</p><p>impossível que a mesma rede neural seja treinada duas vezes.</p><p>Depois de executar 10.000 etapas de treinamento, foram treinadas</p><p>praticamente 10.000 redes neurais diferentes. Obviamente, elas não são</p><p>independentes porque compartilham muitos de seus pesos, mas, apesar</p><p>disso, são todas diferentes. O resultado após a execução da técnica pode</p><p>ser entendido como uma arquitetura média de todas as redes neurais</p><p>executadas anteriormente.</p><p>Ainda há um pequeno, mas importante detalhe técnico a ser discutido.</p><p>Suponha que p = 50%, caso em que, durante a atividade de teste, um</p><p>neurônio seria conectado a duas vezes mais neurônios de entrada do</p><p>que seria (em média) durante o treinamento. Para compensar esse</p><p>fato, precisamos multiplicar os pesos de conexão de entrada de cada</p><p>neurônio por 0.5 após o treinamento. Se não o fizermos, cada neurônio</p><p>receberá um peso de entrada total aproximadamente duas vezes</p><p>maior que o da rede treinada, e provavelmente não apresentará um</p><p>bom desempenho. De modo geral, precisamos multiplicar cada peso</p><p>de conexão de entrada pela probabilidade de manutenção (1–p) após</p><p>o treinamento. Alternativamente, podemos dividir a saída de cada</p><p>neurônio pela probabilidade de mantê-lo durante o treinamento. Para</p><p>Geron (2019), essas alternativas não são perfeitamente equivalentes,</p><p>mas funcionam igualmente bem.</p><p>Para implementar a técnica dropout usando a biblioteca Keras, você</p><p>pode usar a camada keras.layers.Dropout. Durante o treinamento,</p><p>ela descarta aleatoriamente algumas entradas (configurando suas</p><p>32</p><p>saídas para gerar o valor zero) e divide as entradas restantes pela</p><p>probabilidade de manutenção. O código-fonte mostrado a seguir aplica</p><p>a regularização via dropout antes de cada camada Densa, usando uma</p><p>taxa de 0.2:</p><p>model = keras.models.Sequential([</p><p>keras.layers.Flatten(input_shape = [28, 28]),</p><p>keras.layers.Dropout(rate = 0.2),</p><p>keras.layers.Dense(300, activation = ”elu”, kernel_initializer=</p><p>”he_normal”),</p><p>keras.layers.Dropout(rate = 0.2),</p><p>keras.layers.Dense(100, activation = ”elu”, kernel_initializer =</p><p>”he_normal”),</p><p>keras.layers.Dropout(rate = 0.2),</p><p>keras.layers.Dense(10, activation = ”softmax”)</p><p>])</p><p>Se você observar que a rede neural está sobreajustada, pode aumentar</p><p>a taxa de dropout. Por outro lado, você deve tentar diminuir a taxa</p><p>se a rede neural não conseguir generalizar a taxa de erro de forma</p><p>satisfatória ao processar o conjunto de treinamento. Ainda pode ser</p><p>útil aumentar a taxa de dropout para as maiores camadas ocultas e</p><p>reduzi-la para as camadas menores. Além disso, muitas arquiteturas de</p><p>redes neurais usam essa técnica de regularização apenas após a última</p><p>camada oculta. Essa pode ser uma alternativa viável, caso a aplicação</p><p>da técnica em todas as camadas ocultas não gerar um resultado</p><p>satisfatório.</p><p>1.5 Considerações Finais</p><p>Nesta unidade, discutimos algumas técnicas que podem ser usadas</p><p>para melhorar o desempenho, em termos de acurácia</p><p>e tempo</p><p>33</p><p>de processamento, da atividade de treinamento de redes neurais</p><p>profundas. Estudamos a transferência de aprendizado, o pré-</p><p>treinamento não supervisionado, o pré-treinamento em uma tarefa</p><p>auxiliar e a regularização por meio da técnica dropout.</p><p>Provavelmente, você deve estar se perguntando quando tais técnicas</p><p>devem ser usadas. Ainda não há um consenso claro, pois tudo depende</p><p>do tipo de problema que se deseja solucionar. Contudo, algumas dicas</p><p>podem ser úteis:</p><p>• Grandes redes neurais profundas costumam demorar um bom</p><p>tempo na atividade de treinamento. Caso você conheça outra</p><p>rede neural já treinada para uma tarefa similar à que você</p><p>precisa solucionar, é possível usar a transferência de aprendizado</p><p>para reaproveitar algumas camadas ocultas de redes neurais</p><p>devidamente treinadas.</p><p>• Se existem poucos dados de treinamento rotulados com suas</p><p>respectivas classes, existem duas opções: se for possível reunir</p><p>muitos dados de treinamento não rotulados, você pode usá-</p><p>los para treinar um modelo não supervisionado e, em seguida,</p><p>usar os dados rotulados com uma técnica supervisionada. Uma</p><p>outra opção é treinar uma primeira rede neural em uma tarefa</p><p>auxiliar para a qual existem dados de treinamento rotulados e, em</p><p>seguida, reutilizar as camadas inferiores dessa rede para sua tarefa</p><p>real.</p><p>• Por fim, técnicas de regularização, como dropout, podem ser</p><p>usadas para evitar o sobreajuste durantes as atividades de</p><p>treinamento e teste da rede neural profunda.</p><p>34</p><p>Referências</p><p>ARTASANCHEZ, Alberto; JOSHI, Prateek. Artifcial Intelligence with Python: your</p><p>complete guide to building intelligent apps using Python 3.x and Tensorflow 2. 2. ed.</p><p>Birmingham: Packt Publishing, 2020.</p><p>GERON, Aurélien. Hands-on machine learning with Scikit-Learn, Keras, and</p><p>TensorFlow: Concepts, tools, and techniques to build intelligent systems. 2. ed.</p><p>Sebastopol: O’Reilly Media, 2019.</p><p>KERAS. Keras: Deep learning for humans. 2021. Disponível em: https://keras.io/.</p><p>Acesso em: 6 mar. 2021.</p><p>MNIST. Fashion-MNIST dataset of images. 2021. Disponível em: https://www.</p><p>kaggle.com/zalando-research/fashionmnist. Acesso em: 6 mar. 2021.</p><p>about:blank</p><p>about:blank</p><p>about:blank</p><p>35</p><p>Redes neurais convolucionais.</p><p>Autoria: Rogério Ferreira</p><p>Leitura crítica: Edilson José Rodrigues</p><p>Objetivos</p><p>• Apresentar os conceitos básicos relacionados às</p><p>redes neurais convolucionais.</p><p>• Estudar os conceitos de filtros e mapas de</p><p>características, ambos associados ao processamento</p><p>de imagens.</p><p>• Entender os principais componentes da arquitetura</p><p>de uma rede neural convolucional.</p><p>36</p><p>1. Introdução</p><p>Apesar do supercomputador Deep Blue da IBM ter vencido o campeão</p><p>mundial de xadrez Garry Kasparov em 1996, foi apenas recentemente</p><p>que os computadores tornaram-se capazes de realizar tarefas</p><p>aparentemente triviais, como detectar um cachorro em uma imagem</p><p>ou reconhecer palavras. Por que essas tarefas são tão fáceis para nós,</p><p>humanos? A resposta está no fato de que a percepção ocorre em grande</p><p>parte fora da nossa consciência, dentro de módulos visuais, auditivos</p><p>e sensoriais especializados em nosso cérebro. No momento em que</p><p>a informação sensorial chega ao nosso consciente, ela está repleta de</p><p>características de alto nível. Por exemplo: quando você olha a foto de</p><p>um filhote de cachorro, você não pode deixar de perceber o quanto ele</p><p>é encantador! Assim, segundo Geron (2019), a percepção de seres ou</p><p>objetos ao nosso redor não é trivial e, para compreendê-la, devemos</p><p>observar como funcionam os módulos sensoriais do cérebro.</p><p>Redes neurais convolucionais (Convolutional Neural Networks – CNN)</p><p>surgiram a partir do estudo do córtex visual do cérebro, e têm sido</p><p>usadas no reconhecimento de imagens desde a década de 1980. Nos</p><p>últimos anos, graças ao aumento do poder computacional, à quantidade</p><p>de dados de disponíveis e aos métodos para solucionar problemas</p><p>relacionados ao treinamento de redes neurais profundas, as CNN</p><p>conseguiram atingir um desempenho sobre-humano em algumas</p><p>tarefas visuais complexas. Elas potencializam os serviços de pesquisa de</p><p>imagens, carros autônomos, sistemas automáticos de classificação de</p><p>vídeo e muito mais. Além disso, as CNN não se restringem à percepção</p><p>visual: elas também são bem-sucedidas em muitas outras tarefas, como</p><p>reconhecimento de voz e processamento de linguagem natural.</p><p>37</p><p>2. A arquitetura do córtex visual</p><p>Os cientistas David Hubel e Torsten Wiesel realizaram uma série de</p><p>experimentos com gatos em 1959 que forneceram insights importantes</p><p>sobre a estrutura do córtex visual (HUBEL; WIESEL, 1959). Por esse</p><p>trabalho eles receberam o Prêmio Nobel de Fisiologia (ou Medicina)</p><p>em 1981. Em particular, eles mostraram que muitos neurônios no</p><p>córtex visual têm um pequeno campo receptor local, o que significa</p><p>que eles reagem apenas a estímulos visuais localizados em uma região</p><p>limitada do campo visual. Observe a Figura 1, na qual os campos</p><p>receptores locais de cinco neurônios são representados por círculos</p><p>tracejados. Campos receptores de diferentes neurônios podem se</p><p>sobrepor e, juntos, eles revestem todo o campo visual. Além disso, os</p><p>autores mostraram que alguns neurônios reagem a imagens de linhas</p><p>horizontais, enquanto outros reagem apenas a linhas com outros tipos</p><p>de orientação. Assim, dois neurônios podem fazer parte do mesmo</p><p>campo receptor, mas reagem a orientações de linhas diferentes. Eles</p><p>também notaram que alguns neurônios têm campos receptores maiores</p><p>e reagem a padrões mais complexos que são combinações de padrões</p><p>de nível inferior. Essas observações levaram à ideia de que os neurônios</p><p>de nível superior são baseados nas saídas de neurônios de nível inferior</p><p>próximos. Observe na Figura 1 que cada neurônio está conectado</p><p>apenas a alguns neurônios da camada anterior. De acordo com Geron,</p><p>2019), esta arquitetura poderosa é capaz de detectar todos os tipos de</p><p>padrões complexos em qualquer área do campo visual.</p><p>38</p><p>Figura 1 – Arquitetura do córtex visual para possibilitar a detecção</p><p>de imagens</p><p>Fonte: Geron (2019).</p><p>Esses estudos do córtex visual inspiraram uma rede neural chamada</p><p>neocognitron, introduzida em 1980, e que gradualmente evoluiu para</p><p>o que hoje chamamos de redes neurais convolucionais. Tais redes</p><p>apresentam dois novos tipos de camadas: as convolucionais e as</p><p>camadas pooling, descritas nas próximas seções.</p><p>3. Camadas convolucionais</p><p>O tipo de camada mais importante de uma CNN é chamado de</p><p>convolucional. Uma convolução é uma operação matemática</p><p>que “desliza” uma função sobre a outra e mede a integral de sua</p><p>multiplicação. Esse conceito tem fortes conexões com a transformada</p><p>de Fourier e a transformada de Laplace, ambas são muito usadas</p><p>usado no processamento de sinais. Os neurônios na primeira camada</p><p>convolucional não estão conectados a cada neurônio de entrada, mas</p><p>apenas àqueles pertencentes ao seu campo de visão (observe a Figura</p><p>2). Por sua vez, cada neurônio na segunda camada convolucional está</p><p>conectado apenas a neurônios localizados dentro de um pequeno</p><p>retângulo (campo de visão) na primeira camada. Essa arquitetura,</p><p>39</p><p>permite que a rede se concentre em pequenos campos de visão de nível</p><p>mais baixo na primeira camada oculta, e depois os reúna em objetos</p><p>mais complexos de nível superior na próxima camada oculta, e assim</p><p>sucessivamente. Geron (2019) afirma que essa estrutura hierárquica é</p><p>comum em imagens do mundo real, o que é um dos motivos pelos quais</p><p>as CNN funcionam muito bem para reconhecimento de imagens.</p><p>A estratégia utilizada pelas CNN, pode ser descrita, de forma sucinta,</p><p>da seguinte maneira: um neurônio localizado na linha i, coluna j de</p><p>uma determinada camada está conectado às saídas dos neurônios na</p><p>camada anterior localizadas nas linhas i até i + fh–1, colunas j até j + fw–1,</p><p>em que fh e fw são a altura e largura do campo de visão (observe a Figura</p><p>3). Para que uma camada tenha a mesma altura e largura da camada</p><p>anterior, é comum adicionar zeros ao redor das entradas, conforme</p><p>mostrado na Figura</p><p>3. Essa estratégia é chamada de preenchimento com</p><p>zeros. Apesar desta ser a mais comum, existem outras estratégias de</p><p>preenchimento.</p><p>Figura 2 – Camadas de uma CNN com campos receptores locais</p><p>retangulares</p><p>Fonte: Geron (2019).</p><p>40</p><p>Figura 3 – Conexões entre camadas de uma CNN e preenchimento</p><p>com zeros</p><p>Fonte: Geron (2019).</p><p>3.1 Filtros</p><p>Os pesos de um neurônio podem ser representados como uma pequena</p><p>imagem do tamanho de um campo receptor. Por exemplo, a Figura 4</p><p>mostra dois conjuntos possíveis de pesos, chamados filtros (ou kernels</p><p>de convolução). O primeiro é representado como um quadrado preto</p><p>com uma linha branca vertical no meio (é uma matriz 7 × 7 cheia de</p><p>zeros, exceto para a coluna central, que está cheia de uns); os neurônios</p><p>que usam esses pesos ignorarão tudo em seu campo receptor, exceto</p><p>para a linha vertical central, uma vez que todas as entradas serão</p><p>multiplicadas por 0, exceto aquelas localizadas na linha vertical ao</p><p>centro. O segundo filtro é um quadrado preto com uma linha branca</p><p>horizontal no meio. Mais uma vez, os neurônios que usam esses pesos</p><p>ignorarão tudo em seu campo receptor, exceto a linha horizontal ao</p><p>centro.</p><p>Agora, se todos os neurônios em uma camada usarem o mesmo filtro</p><p>de linha vertical, e você alimentar a rede com a imagem de entrada</p><p>Preenchimento com zeros</p><p>41</p><p>mostrada na Figura 4 (a imagem inferior), a camada produzirá a</p><p>imagem superior esquerda. Observe que as linhas brancas verticais</p><p>são realçadas enquanto o restante fica borrado. Da mesma forma,</p><p>você obtém a imagem superior direita se todos os neurônios usam</p><p>o mesmo filtro de linha horizontal; observe que as linhas brancas</p><p>horizontais são realçadas enquanto o restante é desfocado. Assim, uma</p><p>camada cheia de neurônios usando o mesmo filtro produz um mapa de</p><p>características que destaca as áreas em uma imagem que mais ativam o</p><p>filtro. Obviamente, você não precisa definir os filtros manualmente: em</p><p>vez disso, durante o treinamento, a camada convolucional aprenderá</p><p>automaticamente os filtros mais úteis para sua tarefa e as camadas</p><p>acima aprenderão a combiná-los em padrões mais complexos.</p><p>Figura 4 – Aplicando filtros diferentes para obter dois mapas de</p><p>características</p><p>Fonte: Geron (2019).</p><p>42</p><p>3.2 Empilhando múltiplos mapas de características</p><p>Até agora, para simplificar, representamos a saída de cada camada</p><p>convolucional como uma camada 2D mas, na realidade, tais camadas</p><p>têm vários filtros (você decide quantos) e elas produzem um mapa</p><p>de características por filtro. Essa estratégia é representada com</p><p>mais precisão em 3D, como você pode observar na Figura 5. Existe</p><p>um neurônio por pixel em cada mapa de características, e todos os</p><p>neurônios em um determinado mapa compartilham os mesmos</p><p>parâmetros, ou seja, os mesmos pesos. Neurônios em mapas de</p><p>características diferentes usam parâmetros diferentes. O campo</p><p>receptor de um neurônio é o mesmo descrito anteriormente, mas se</p><p>estende por todos os mapas das camadas anteriores. Em suma, uma</p><p>camada convolucional aplica simultaneamente vários filtros treináveis</p><p>às suas entradas, tornando-a capaz de detectar várias características em</p><p>qualquer lugar em suas entradas. As imagens de entrada também são</p><p>compostas por várias subcamadas: uma por canal de cor. Normalmente</p><p>existem três: vermelho, verde e azul (red, green e blue – RGB). As imagens</p><p>em tons de cinza têm apenas um canal, mas algumas imagens podem</p><p>ter muito mais – por exemplo, imagens de satélite que capturam</p><p>frequências extras de luz, como infravermelho.</p><p>43</p><p>Figura 5 – Camadas convolucionais com múltiplos mapas de</p><p>características, e imagens com três canais de cores</p><p>Fonte: Geron (2019).</p><p>4. Camadas Pooling</p><p>Compreender os conceitos relacionados às camadas convolucionais</p><p>facilita entender o funcionamento das camadas pooling. Seu objetivo é</p><p>reduzir a imagem de entrada que está sendo processada, com o intuito</p><p>de diminuir o custo computacional, o uso de memória e o número de</p><p>parâmetros, limitando assim o risco de sobreajuste (ARTASANCHEZ;</p><p>JOSHI, 2020).</p><p>Filtros</p><p>44</p><p>Assim como nas camadas convolucionais, cada neurônio em uma</p><p>camada pooling está conectado às saídas de um número limitado de</p><p>neurônios na camada anterior, localizados dentro de um pequeno</p><p>campo receptor retangular. Você deve definir o seu tamanho, o tipo de</p><p>preenchimento e o tamanho do passo (quantidade de neurônios de um</p><p>campo receptor). Um neurônio de pooling não tem pesos; tudo o que</p><p>ele faz é agrupar as entradas usando uma função de agregação, como</p><p>o número máximo ou a média. A Figura 6 mostra uma camada pooling</p><p>máxima, que é o tipo mais comum. Neste exemplo, é utilizado um kernel</p><p>pooling de tamanho 2 × 2, tamanho do passo igual a 2 (tanto na vertical</p><p>quanto na horizontal) e sem estratégia de preenchimento. Apenas o</p><p>valor máximo de entrada em cada campo receptor é enviado à próxima</p><p>camada, enquanto as outras entradas são descartadas. Por exemplo,</p><p>no campo receptor inferior esquerdo na Figura 6, os valores de entrada</p><p>são 1, 5, 3, 2, portanto, apenas o valor máximo 5 é propagado para a</p><p>próxima camada. Por causa do tamanho do passo igual a 2, a imagem de</p><p>saída tem metade da altura e metade da largura da imagem de entrada,</p><p>arredondada para baixo, pois não está sendo usado preenchimento.</p><p>Figura 6 – Camada pooling com tamanho do passo igual a 2 e função</p><p>max.</p><p>Fonte: Geron (2019).</p><p>45</p><p>5. Arquiteturas de redes neurais</p><p>convolucionais</p><p>As típicas arquiteturas CNN, como descreve Geron (2019), empilham</p><p>algumas camadas convolucionais, cada uma geralmente seguida por</p><p>uma camada com a função de ativação ReLU. Na sequência, segue</p><p>uma camada pooling, depois outras camadas convolucionais seguidas</p><p>por camadas ReLU e uma camada pooling, e assim sucessivamente.</p><p>A imagem fica cada vez menor à medida que avança pela rede, mas,</p><p>também, fica cada vez mais profunda (ou seja, com mais mapas de</p><p>características) graças às camadas convolucionais, como pode ser</p><p>observado na Figura 7. No topo da pilha, uma rede neural feed-forward</p><p>regular é adicionada, composta de algumas camadas totalmente</p><p>conectadas, e a camada final realiza a previsão por meio do uso de uma</p><p>função de ativação como softmax, que produz probabilidades de classes</p><p>estimadas.</p><p>Figura 7 – Arquitetura típica de uma CNN.</p><p>Fonte: Geron (2019).</p><p>O código-fonte exibido a seguir apresenta a implementação de uma CNN</p><p>simples com a biblioteca Keras (KERAS, 2021) para processar as imagens</p><p>do conjunto de dados MNIST (MNIST, 2021).</p><p>model = keras.models.Sequential ([</p><p>keras.layers.Conv2D (64, 7,</p><p>46</p><p>activation=”relu”,</p><p>padding=”same”, input_shape = [28, 28, 1]),</p><p>keras.layers.MaxPooling2D (2),</p><p>keras.layers.Conv2D (128, 3, activation=”relu”, padding=”same”),</p><p>keras.layers.Conv2D (128, 3, activation=”relu”, padding=”same”),</p><p>keras.layers.MaxPooling2D (2),</p><p>keras.layers.Conv2D (256, 3, activation=”relu”, padding=”same”),</p><p>keras.layers.Conv2D (256, 3, activation=”relu”, padding=”same”),</p><p>keras.layers.MaxPooling2D (2),</p><p>keras.layers.Flatten (),</p><p>keras.layers.Dense (128, activation=”relu”),</p><p>keras.layers.Dropout (0.5),</p><p>keras.layers.Dense (64, activation=”relu”),</p><p>keras.layers.Dropout (0.5),</p><p>keras.layers.Dense (10, activation=”softmax”)</p><p>])</p><p>Vamos examinar a arquitetura definida para o modelo do código-fonte:</p><p>• A primeira camada usa 64 filtros razoavelmente grandes (7 ×</p><p>7), mas não é definido valor para o tamanho do passo porque</p><p>as imagens de entrada não são grandes. Também é definido o</p><p>formato da entrada (input_shape = [28, 28, 1]), porque as imagens</p><p>são de 28 × 28 pixels, com um único canal de cor (ou seja, tons de</p><p>cinza).</p><p>• Em seguida, temos uma camada pooling do tipo max que usa um</p><p>tamanho de pool igual 2, assim, divide cada dimensão espacial por</p><p>um fator de 2.</p><p>• Em seguida, repetimos a mesma estrutura duas vezes: duas</p><p>camadas convolucionais seguidas por uma camada pooling do tipo</p><p>max. Para imagens maiores, poderíamos repetir essa estrutura</p><p>47</p><p>várias vezes (o número de repetições é um hiperparâmetro</p><p>ajustável).</p><p>• Observe que o número de filtros aumenta à medida que</p><p>avançamos na arquitetura CNN em direção à camada de saída</p><p>(inicialmente é 64, depois 128, depois 256): faz sentido que</p><p>a quantidade de filtros aumente, uma vez que o número de</p><p>características de baixo nível costuma ser pequeno – por exemplo,</p><p>pequenos círculos, linhas horizontais. Porém, existem muitas</p><p>maneiras diferentes de combiná-los em características de nível</p><p>superior. É uma prática comum dobrar o número de filtros após</p><p>cada camada de agrupamento, uma vez que ela divide cada</p><p>dimensão espacial por um fator de 2. Assim, podemos dobrar</p><p>o número de mapas de características na próxima camada sem</p><p>medo de aumentar excessivamente o número de parâmetros, uso</p><p>de memória ou carga computacional.</p><p>• Na sequência é definida a rede totalmente conectada, composta</p><p>por duas camadas ocultas (densas) e uma camada de saída</p><p>(densa). Observe que devemos nivelar suas entradas, uma vez</p><p>que uma rede densa espera uma matriz 1D de atributos para cada</p><p>instância. Também adicionamos duas camadas do tipo dropout,</p><p>com uma taxa de 50% cada, para reduzir o sobreajuste.</p><p>Este CNN atinge mais de 92% de acurácia no conjunto de teste. Não é</p><p>um resultado excepcional, contudo, o desempenho é muito melhor do</p><p>que alcançaríamos com uma simples rede neural multi-camadas.</p><p>6. Considerações Finais</p><p>Nessa unidade, você pode conhecer os conceitos relacionados às redes</p><p>neurais convolucionais (CNN) e ao processamento de imagens. As CNN</p><p>foram inspiradas na arquitetura do córtex visual, particularmente no</p><p>comportamento de muitos neurônios que possuem um pequeno campo</p><p>48</p><p>receptor local. Isso significa que eles reagem apenas a estímulos visuais</p><p>localizados em uma região limitada do campo visual. Na arquitetura</p><p>de uma CNN, os neurônios da primeira camada convolucional não</p><p>estão conectados a todos os neurônios da imagem de entrada, mas</p><p>apenas àqueles pertencentes ao seu campo de visão. De forma similar,</p><p>cada neurônio na segunda camada convolucional está conectado</p><p>apenas a neurônios localizados dentro de um pequeno retângulo</p><p>(campo de visão) na primeira camada. Essa estrutura permite à rede</p><p>concentrar-se em pequenos campos de visão conforme avança em sua</p><p>arquitetura. Além das camadas convolucionais você estudou as camadas</p><p>pooling, cujo objetivo é reduzir o tamanho da imagem que está sendo</p><p>processada, para diminuir o custo de processamento, uso de memória</p><p>e número de parâmetros. Por fim, você conheceu como implementar a</p><p>arquitetura básica de uma CNN utilizando a biblioteca KERAS. A partir do</p><p>entendimento deste exemplo básico, você poderá utilizar a biblioteca na</p><p>construção de redes convolucionais mais complexas.</p><p>Referências</p><p>ARTASANCHEZ, Alberto; JOSHI, Prateek. Artifcial Intelligence with Python: your</p><p>complete guide to building intelligent apps using Python 3.x and Tensorflow 2. 2. ed.</p><p>Birmingham: Packt Publishing, 2020.</p><p>GERON, Aurélien. Hands-on machine learning with Scikit-Learn, Keras, and</p><p>TensorFlow: Concepts, tools, and techniques to build intelligent systems. 2. ed.</p><p>Sebastopol: O’Reilly Media, 2019.</p><p>KERAS. Keras: Deep learning for humans. 2021. Disponível em: https://keras.io/.</p><p>Acesso em: 6 mar. 2021.</p><p>MNIST. Fashion-MNIST dataset of images. 2021. Disponível em: https://www.</p><p>kaggle.com/zalando-research/fashionmnist. Acesso em: 6 mar. 2021.</p><p>about:blank</p><p>about:blank</p><p>49</p><p>Redes neurais recorrentes.</p><p>Autoria: Rogério Ferreira</p><p>Leitura crítica: Edilson José Rodrigues</p><p>Objetivos</p><p>• Conhecer os princípios básicos das redes neurais</p><p>recorrentes.</p><p>• Apresentar os conceitos de células de memória e</p><p>sequências de entrada e saída.</p><p>• Estudar o funcionamento das séries temporais com</p><p>o uso de redes neurais recorrentes.</p><p>50</p><p>1. Introdução</p><p>Prever o futuro é algo que as pessoas buscam fazer o tempo todo, seja</p><p>na tentativa de terminar a frase de um amigo ou descobrir o preço de</p><p>um imóvel com base nas suas características. Neste tema, discutiremos</p><p>as redes neurais recorrentes (Recurrent Neural Networks – RNN), uma</p><p>classe de redes que pode prever o futuro, obviamente até um certo</p><p>ponto. Elas são capazes de analisar dados de séries temporais, como</p><p>preços de ações, e informar quando comprar ou vendê-las. Em sistemas</p><p>de direção autônoma, elas podem antecipar as trajetórias dos carros e</p><p>ajudar a evitar acidentes. De modo geral, elas funcionam com conjuntos</p><p>de dados de comprimentos arbitrários, em vez de entradas de tamanho</p><p>fixo como nas demais redes neurais. Por exemplo, elas podem processar</p><p>frases, documentos ou amostras de áudio para criar aplicações de</p><p>processamento de linguagem natural, como tradução automática ou</p><p>transcrição de voz para texto. Neste capítulo, estudaremos os conceitos</p><p>fundamentais subjacentes às RNN, como treiná-las usando o algoritmo</p><p>de retropropagação em função do tempo, e ainda, exploraremos as</p><p>principais dificuldades que elas enfrentam.</p><p>2. As redes neurais e camadas recorrentes</p><p>De formal geral, nas redes neurais feed-forward, o processamento dos</p><p>sinais flui apenas em uma direção, da camada de entrada para a camada</p><p>de saída. Uma rede neural recorrente funciona de forma muito parecida,</p><p>exceto pelo fato que ela também possui conexões no sentido contrário.</p><p>Vamos analisar a arquitetura mais simples possível para uma RNN,</p><p>composta de um neurônio recebendo entradas, produzindo uma saída</p><p>e enviando essa saída de volta para si mesmo, conforme mostrado na</p><p>Figura 1 à esquerda. Em cada etapa de tempo t (também chamada de</p><p>quadro), esse neurônio recorrente recebe as entradas x(t), bem como</p><p>sua própria saída da etapa de tempo anterior, y(t – 1). Como não há</p><p>51</p><p>saída anterior na primeira etapa de tempo, ela geralmente é definida</p><p>como 0. Podemos representar essa pequena rede em função do tempo,</p><p>conforme mostrado na Figura 1 à direita, contendo o mesmo neurônio</p><p>recorrente representado uma vez por intervalo de tempo.</p><p>Figura 1 – Um neurônio recorrente (à esquerda) representado em</p><p>função do tempo (à direita)</p><p>Fonte: Geron (2019).</p><p>É possível criar facilmente uma camada de neurônios recorrentes.</p><p>Em cada etapa de tempo t, cada neurônio recebe o vetor de dados de</p><p>entrada x(t) e o vetor de dados de saída da etapa de tempo anterior</p><p>y(t – 1), conforme mostrado na Figura 2. Portanto, observe que tanto as</p><p>entradas quanto as saídas são utilizados como dados de entrada. Cada</p><p>neurônio recorrente tem dois conjuntos de pesos: um para as entradas</p><p>x(t) e outro para as saídas do intervalo de tempo anterior, y(t – 1). Vamos</p><p>chamar esses vetores de peso de wx e wy. Se considerarmos toda a</p><p>camada recorrente em vez de apenas um neurônio, podemos colocar</p><p>todos os vetores de peso em duas matrizes de peso, Wx e Wy. Assim, o</p><p>vetor de saída de toda a camada recorrente pode então ser calculado</p><p>como mostrado na Equação 1 (b é o vetor com os valores de viés e (·) é</p><p>a função de ativação (ARTASANCHEZ; JOSHI, 2020).</p><p>Equação (1)</p><p>52</p><p>Figura 2 – Uma camada de neurônios recorrentes (à esquerda)</p><p>representada em função do tempo (à direita)</p><p>Fonte: GERON (2019).</p><p>2.1 Células de memória</p><p>Considerando que a saída de um neurônio recorrente na etapa de</p><p>tempo t é uma função de todas as entradas das etapas de tempo</p><p>anteriores, pode-se dizer que ele tem possui uma espécie de memória.</p><p>A parte de uma rede neural que mantem armazenado algum tipo de</p><p>estado em intervalos de tempo diferentes é chamada de célula de</p><p>memória (ou simplesmente célula). Um único neurônio recorrente, ou</p><p>uma camada de neurônios recorrentes, é uma célula básica, capaz de</p><p>aprender apenas padrões curtos (normalmente cerca de dez passos</p><p>de comprimento, dependendo da tarefa). Em geral, o estado de uma</p><p>célula na etapa de tempo t, denotado h(t) (o h significa oculto), é uma</p><p>função de algumas entradas nessa etapa de tempo e seu estado na</p><p>etapa de tempo anterior: h (t) = f (h(t – 1), x(t)). Sua saída na etapa de</p><p>tempo t, denotada por y(t), também é uma função do estado anterior e</p><p>das entradas atuais. No caso das células mais básicas discutidas</p><p>até o</p><p>momento, a saída é simplesmente igual ao estado, mas em células mais</p><p>complexas, muitas vezes, esse não é o caso, conforme mostrado na</p><p>Figura 3.</p><p>53</p><p>Figura 3 – O estado de uma célula oculta e sua saída podem ser</p><p>diferentes</p><p>Fonte: Geron (2019).</p><p>2.2 Sequências de entrada e saída</p><p>Um RNN pode processar, simultaneamente, uma sequência de entradas</p><p>e gerar uma sequência de saídas (observe a rede superior esquerda na</p><p>Figura 4). Este tipo de rede é chamado de sequência-para-sequência,</p><p>sendo capaz de processar sequências e prever dados de séries</p><p>temporais como preços de ações: você a alimenta a rede com os preços</p><p>dos últimos N dias, e ela irá prever os preços do dia seguinte (ou seja,</p><p>de N–1 dias atrás até amanhã). Alternativamente, você pode alimentar a</p><p>rede com uma sequência de entradas e ignorar todas as saídas, exceto a</p><p>última (observe a rede no canto superior direito na Figura 4). Esta rede é</p><p>chamada de sequência-para-vetor. Por exemplo, você poderia alimentar</p><p>a rede com uma sequência de palavras correspondentes a crítica de um</p><p>filme, e a rede geraria uma pontuação para a expressão dos sentimentos</p><p>contida no texto, por exemplo, de -1 (ódio) até +1 amor).</p><p>Por outro lado, você pode alimentar a rede com o mesmo vetor de</p><p>entrada repetidamente a cada etapa de tempo, e deixá-la produzir</p><p>uma sequência de valores (observe a rede inferior esquerda da Figura</p><p>4). Este tipo de rede é chamado de vetor-para sequência. Neste caso,</p><p>54</p><p>por exemplo, a entrada pode ser uma imagem (ou a saída de uma</p><p>rede neural convolucional) e a saída pode ser uma legenda para essa</p><p>imagem. Por fim, você poderia ter uma rede de sequência-para-vetor,</p><p>chamada de codificador, seguida por uma rede de vetor-para-sequência,</p><p>chamada de decodificador (observe a rede inferior direita da Figura</p><p>4). Por exemplo, essa estratégia pode ser usada para traduzir uma</p><p>frase de um idioma para outro. Você alimentaria a rede com uma frase</p><p>em um idioma, o codificador converteria essa frase em uma única</p><p>representação vetorial e, em seguida, o decodificador faria o processo</p><p>inverso, traduzindo esse vetor para uma frase em outro idioma.</p><p>Conforme Geron (2019) este modelo de duas etapas, chamado de</p><p>codificador-decodificador, funciona melhor do que tentar traduzir frases</p><p>em tempo real com uma única RNN sequência-a-sequência: as últimas</p><p>palavras de uma frase podem afetar a tradução das primeiras, então</p><p>você precisa esperar pela frase inteira antes de traduzi-la.</p><p>3. Previsão de séries temporais</p><p>Suponha que você esteja estudando o número de usuários ativos por</p><p>hora em seu site, o histórico de temperaturas diárias da sua cidade ou a</p><p>saúde financeira de sua empresa, medida trimestralmente por meio de</p><p>várias métricas. Em todos esses casos, os dados serão uma sequência</p><p>de um ou mais valores por intervalo de tempo. Esse é o conceito de</p><p>série temporal. Nos primeiros dois exemplos, há um único valor por</p><p>intervalo de tempo, então essas são séries temporais univariadas,</p><p>enquanto no exemplo financeiro existem vários valores por intervalo de</p><p>tempo (por exemplo, a receita da empresa, dívida e assim por diante),</p><p>então é uma série temporal multivariada. Uma tarefa comum é prever</p><p>valores futuros, o que é chamado de previsão, ou preencher “espaços</p><p>em branco” da série, ou seja, preencher valores ausentes do passado.</p><p>Segundo Geron (2019), essa tarefa é chamada de imputação. Por</p><p>exemplo, a Figura 5 apresenta três séries temporais univariadas, cada</p><p>55</p><p>uma delas com 50 intervalos de tempo, e o objetivo é prever o valor do</p><p>próximo intervalo (representado pelo x) para cada uma delas.</p><p>Figura 4 – Possibilidades de sequências de entrada e saída</p><p>Fonte: Geron (2019).</p><p>Saídas ignoradas</p><p>Codificador Decodificador</p><p>56</p><p>Figura 5 – Previsão de séries temporais</p><p>Fonte: Geron (2019).</p><p>Vamos analisar um exemplo utilizando uma série temporal gerada pela</p><p>função generate_time_series(), exibida a seguir:</p><p>def generate_time_series(batch_size, n_steps):</p><p>freq1, freq2, offsets1, offsets2 = np.random.rand(4,</p><p>batch_size, 1)</p><p>time = np.linspace(0, 1, n_steps)</p><p>series = 0.5 * np.sin((time–offsets1) * (freq1 * 10 + 10)) #onda 1</p><p>series += 0.2 * np.sin((time–offsets2) * (freq2 * 20 + 20)) #onda 2</p><p>series += 0.1 * (np.random.rand(batch_size, n_steps)–0.5) #ruído</p><p>return series[..., np.newaxis].astype(np.float32)</p><p>Esta função cria a quantidade de séries temporais solicitadas (por meio</p><p>do argumento batch_size), cada uma com comprimento do argumento</p><p>n_steps, e há apenas um valor por intervalo de tempo em cada série (ou</p><p>seja, todas as séries são univariadas). A função retorna uma matriz de</p><p>57</p><p>formato [batch_size, n_steps, 1], em que cada série é a soma de duas</p><p>ondas senoidais de amplitudes fixas, mas frequências e fases aleatórias,</p><p>mais uma pequena parte de ruído. O trecho de código a seguir,</p><p>implementado com a biblioteca Keras (KERAS, 2021), mostra a criação de</p><p>um conjunto de treinamento, um conjunto de validação e um conjunto</p><p>de teste que utiliza esta função:</p><p>n_steps = 50</p><p>series = generate_time_series(10000, n_steps + 1)</p><p>X_train, y_train=series[:7000, :n_steps], series[:7000,-1]</p><p>X_valid, y_valid = series[7000:9000, :n_steps],</p><p>series[7000:9000, -1]</p><p>X_test, y_test = series[9000:, :n_steps], series[9000:, -1]</p><p>X_train contém 7.000 séries temporais (ou seja, seu formato é [7.000,</p><p>50, 1]), enquanto X_valid contém 2.000 séries temporais (da 7.000 até</p><p>a 8.999) e X_test contém 1.000 séries temporais (da 9.000 até a 9.999).</p><p>Como queremos prever um único valor para cada série, os resultados</p><p>serão vetores de uma coluna (por exemplo, y_train tem um formato de</p><p>[7000, 1]).</p><p>3.1 Métricas de desempenho</p><p>Antes de começarmos a usar RNN, é importante entender algumas</p><p>métricas de desempenho, ou então podemos imaginar que nosso</p><p>modelo funciona muito bem, quando na verdade ele faz previsões</p><p>bastante ruins. A abordagem mais simples é prever o último valor de</p><p>cada série. Isso é chamado de previsão “ingênua” (do inglês naive), e às</p><p>vezes é surpreendentemente difícil melhorar o seu desempenho. Para</p><p>o exemplo gerado, temos um erro quadrático médio de cerca de 0.020,</p><p>como mostrado no trecho de código a seguir:</p><p>58</p><p>>>> y_pred = X_valid[:, -1]</p><p>>>> np.mean(keras.losses.mean_squared_error(y_valid,</p><p>y_pred))</p><p>0.020211367</p><p>Outra abordagem simples é usar uma rede totalmente conectada. Uma</p><p>vez que ela precisa uma lista simples de atributos para cada entrada,</p><p>precisamos adicionar uma camada do tipo Flatten. Vamos usar um</p><p>modelo de regressão linear simples para que cada previsão seja uma</p><p>combinação linear dos valores na série temporal, com exibido no trecho</p><p>de código a seguir:</p><p>model = keras.models.Sequential([</p><p>keras.layers.Flatten(input_shape=[50, 1]),</p><p>keras.layers.Dense(1)</p><p>])</p><p>Se compilarmos este modelo usando a função de perda do erro</p><p>quadrático médio e um otimizador do tipo adam, realizar o treinamento</p><p>por 20 épocas e avaliá-lo no conjunto de validação, obtemos um erro</p><p>quadrático médio de cerca de 0.004. O desempenho é muito melhor do</p><p>que a abordagem anterior.</p><p>3.2 Implementação de uma RNN simples</p><p>O trecho de código exibido a seguir mostra a definição de uma rede</p><p>neural recorrente simples:</p><p>model = keras.models.Sequential([</p><p>59</p><p>keras.layers.SimpleRNN(1, input_shape=[None, 1])</p><p>])</p><p>Ela contém uma única camada, com um único neurônio, como foi</p><p>mostrado na Figura 1. Não precisamos especificar o comprimento das</p><p>sequências de entrada, uma vez que uma rede neural recorrente pode</p><p>processar qualquer número de etapas de tempo, por isso definimos a</p><p>primeira dimensão de entrada como None). Por padrão, a camada do</p><p>tipo SimpleRNN usa a função de ativação tangente hiperbólica. Ela</p><p>funciona assim: o estado inicial h(init) é definido como 0 e é passado para</p><p>um único neurônio recorrente, junto com o valor da primeira etapa de</p><p>tempo, x(0). O neurônio calcula uma soma ponderada desses valores</p><p>e aplica a função de ativação tangente hiperbólica ao resultado, o que</p><p>gera a primeira saída, y0. Em um RNN simples, essa saída também</p><p>é o novo</p>

Mais conteúdos dessa disciplina