Visão computacional na era do deep learning

Durante décadas, o reconhecimento de imagem foi um dos grandes desafios da inteligência artificial.

Antes que você comece a sua leitura, preciso divulgar uma nota informativa: esse texto é possivelmente mais longo do que a maioria dos posts que você costuma ler. Espero conseguir prender a sua atenção até o final.  

Durante décadas, o reconhecimento de imagem foi um dos grandes desafios da inteligência artificial (computadores aprenderam a ver apenas recentemente) [1]. Escrevo esse texto rodeado pelos meus cadernos e livros, de tamanhos, volumes e cores diferentes. Olho pela janela e vejo o emaranhado de prédios no meu entorno. Cerca de um terço dos neurônios em meu córtex cerebral estão envolvidos no processamento de informações visuais [2]. Para um computador, fazer isto é uma confusão de cores, brilho e sombras. Era consenso entre pesquisadores de IA que, sem algum tipo de modelo de como o mundo funcionava e tudo o que havia nele, um computador nunca seria capaz de distinguir cenas complexas e suas partes [3]. O campo da “visão computacional” era composto por um bando de algoritmos que tentavam identificar locomoção, elementos na cena, alinhamento e reconstrução disso tudo em 3D [3]. A perspectiva de ver como um humano era, no máximo, um sonho distante. 

Isso mudou em 2012 com um paper que apresentava um sistema chamado AlexNet [4], que abordava o reconhecimento de imagem usando uma técnica chamada deep learning. A partir de então, criou-se um burburinho na comunidade de visão computacional em torno da técnica. É possível que você já tenha ouvido falar do termo. Mas, afinal o que é isso? Deep learning é um subcampo de machine learning, que por sua vez, é um subcampo da inteligência artificial. Ser um subcampo de machine learning já diz muito a respeito de deep learning, já que ML está especificamente interessada em reconhecimento de padrões e aprendizagem a partir de dados. A técnica consiste em uma rede neural, que é chamada de “profunda” porque seus neurônios artificiais (também chamados de nós neurais ou Perceptrons) estão dispostos em muitas camadas. À medida em que novas imagens são mostradas à rede, ela adivinha o que há nelas. Inevitavelmente, as primeiras tentativas saem erradas, mas após cada suposição as conexões entre suas camadas de neurônios são ajustadas, até que a máquina aprende a produzir um rótulo correspondente ao que os desenvolvedores querem. Esse ajuste é feito por cálculos de pesos. Com o passar do tempo, as camadas internas de tais redes vieram a se assemelhar ao córtex visual humano: as primeiras camadas detectam características simples, como bordas, enquanto as camadas posteriores realizam tarefas mais complexas, como escolher formas. Isto revolucionou o campo da visão computacional. 

A história das redes neurais e do deep learning é longa e um tanto confusa. Muitos podem ficar surpresos em saber que o deep learning existe desde os anos 1940, passando por várias mudanças de nome, incluindo cibernética, conexionismo e a mais conhecida, Redes Neurais Artificiais [7]. Apesar de já existir anos antes da publicação do paper, o deep learning era considerado impraticável. AlexNet mostrou que a técnica podia ser usada para resolver problemas do mundo real e ser executada rapidamente em computadores baratos como os PCs, notebooks, e Macs usados por todos nós, sem precisar de supercomputadores. Hoje, praticamente todos os sistemas de IA dos quais você já ouviu falar – Siri, Alexa, AlphaGo, Google Translate – dependem da técnica.     

A desvantagem do deep learning é que ele requer grandes quantidades de dados especializados. Para poder reconhecer rostos, um sistema usando deep learning precisa ser treinado em dezenas de milhares de retratos. A IA profunda não reconhecerá um objeto a menos que esse objeto tenha sido mostrado a ela milhares de vezes. A primeira coisa que qualquer um que trabalha com deep learning aprende é a coletar e rotular dados em escala industrial. Nos últimos anos, todos nós nos juntamos ao esforço: o reconhecimento facial de hoje é particularmente bom porque as pessoas marcam a si mesmas em fotos que enviam para redes sociais. O Google, por exemplo, pede aos usuários que rotulem objetos que seus IA profundos ainda estão aprendendo a identificar: é isso que você está fazendo quando pega um daqueles testes do tipo “você é um robô?”, nos quais precisa selecionar todos os quadrados que contêm pontes, faixas de pedestres ou postes de luz.   

Mesmo assim, existem pontos cegos. Sabe-se que os carros autônomos têm dificuldades com sinalização incomum, como os sinais de parada azuis encontrados no Havaí [5] ou placas obscurecidas por terra ou árvores. Em 2017, um grupo de cientistas da computação da Universidade da Califórnia, em Berkeley, apontou que, na Internet, quase todas as imagens marcadas como “quartos” são “claramente encenadas e retratam uma cama feita a 2-3 metros de distância” [6]. Como resultado, as redes neurais baseadas em deep learning têm dificuldade em reconhecer quartos reais. É possível, porém, preencher esses pontos cegos por meio de esforço concentrado. Por exemplo, em um projeto que participei foram usados modelos de deep learning para ensinar o computador a ler raios-X. A parte que estive envolvido lidava com fraturas ósseas. Pedimos a cirurgiões e radiologistas que rotulassem uma biblioteca de imagens, indicando o que era ou não fratura óssea, que tipo de fratura se tratava e onde ela havia ocorrido. 

Minha ideia aqui é explicar como funciona este tipo de rede para a visão computacional. Não será usada nenhuma matemática, apenas esquemas gráficos para ajudar na visualização dos conceitos. Vamos começar com um modelo básico de rede neural, criado nos anos 1950 e chamado de Perceptron. Este modelo consegue aprender automaticamente os pesos necessários para classificar uma determinada entrada (por exemplo, uma imagem) sem precisar de intervenção humana. Um exemplo da arquitetura Perceptron pode ser visto na Figura 1. Este procedimento de treinamento automático forma a base do Stochastic Gradient Descent (SGD), que ainda hoje é usado para treinar redes neurais muito profundas (as chamadas very deep learning).

Perceptron
Figura 1: Arquitetura Perceptron. Fonte: Adrian Rosebrock.

Os pesos (weights) são os cálculos gerados por cada insumo (input) que é apresentado para a rede. Os pesos são somados e a rede neural é ativada pela step function (chamada em português de função degrau). Em matemática, uma função é chamada de degrau se ela puder ser escrita como uma combinação linear finita de funções indicadoras de intervalos (esses intervalos são importantes porque definem a classe a que o input pertence). No caso do Perceptron original, a função degrau é uma função chamada Heaviside. As funções de ativação são as unidades de tomada de decisão das redes neurais. Elas calculam a saída de um nó neural. É possível observar que o Perceptron é uma rede neural primitiva, que possui apenas uma camada de neurônio. Por isso, é chamada de single layer neural network. A saída dessa rede é uma resposta binária: 0 (que significa não ou falso) e 1 (que significa sim ou verdadeiro). Em outras palavras, todas as classes (0 ou 1) podem ser separadas por uma única linha, consequentemente é chamada de linear, como ilustrado abaixo na Figura 2.   

linearly separable
Figura 2: Separação linear. Fonte: automaticaddison.com

Até 1969 a técnica Perceptron era tudo o que a comunidade que trabalhava com deep learning conseguia entregar. Neste ano, Marvin Minsky e Seymour Papert lançaram um livro chamado Perceptrons [9], em que faziam a primeira tentativa de desenvolver uma teoria geral para autômatos (a.k.a. robôs) e computação. A importância desse trabalho foi demonstrar que um Perceptron com uma função de ativação era meramente um classificador linear, incapaz de resolver problemas não-lineares, como o chamado problema XOR (pronuncia-se “exclusive or” – “ou exclusivo”). Neste tipo de problema, é impossível fazer uma classificação usando apenas uma linha reta. Tente fazer isso na Figura 3, separando as estrelas azuis dos círculos vermelhos. Uma função XOR deve retornar um valor verdadeiro (1) se as duas entradas não forem iguais e um valor falso (0) se o forem.

XOR problem
Figura 3: Exemplo de problema XOR.  Fonte: Adrian Rosebrock.

Minsky e Papert argumentavam (corretamente)  que não existia até então recursos computacionais, principalmente capacidade de processamento, para se construir redes neurais profundas. Esta tentativa de “nivelar as expectativas” quase matou o deep learning, já que levou à retirada maciça de investimentos nas pesquisas sobre redes neurais. Por sorte, nos anos 1990 uma joint venture de universidades americanas e canadenses, com pesquisadores como Geoffrey Hinton, Yann LeCun e Yoshua Bengio a frente, a colocou de volta no páreo com a pesquisa que resultou na criação do algoritmo de Backpropagation [10]. A Figura 4 mostra como essas ondas de pesquisa aconteceram.

The three historical waves GOODFELLOW BENGIO
Figura 4: As ondas de pesquisa em deep learning (pelos nomes usados nas respectivas épocas). Fonte: David Lopes de Macêdo [11]. 

O algoritmo de Backpropagation permitiu o treinamento de redes neurais de multicamadas do tipo feedfoward (multi-layer feedforward). Combinado com funções de ativação não-lineares, era possível aprender funções não-lineares para resolver problemas do tipo XOR. A Figura 5 mostra a arquitetura de uma rede multicamadas do tipo feedfoward com uma camada de entrada (3 nós), duas camadas ocultas (2 nós na primeira camada e 3 nós na segunda camada) e uma camada de saída (2 nós).

feedfoward
Figura 5: Exemplo de redes multicamadas do tipo feedfoward. Fonte: Adrian Rosebrock.

Os estudos a respeito de redes neurais levou ao entendimento de que elas eram “aproximadoras universais” [10]. Isso quer dizer que eram capazes de aproximar qualquer função contínua. Com a capacidade de processamento dos computadores atuais, aliada à imensa quantidade e variedade de dados disponíveis, tornou possível se treinar redes com muito mais camadas ocultas, que são capazes de aprendizado hierárquico, onde conceitos simples são aprendidos nas camadas inferiores e padrões mais abstratos nas camadas superiores. Talvez o melhor exemplo para deep learning sejam as redes neurais convolucionais (Convolutional Neural Networks – CNN), criadas por LeCun e colaboradores [12] em que a rede multicamadas e o algoritmo de Backpropagation foram aplicados ao reconhecimento de caracteres manuscritos. O modelo de LeCun aprendeu automaticamente os padrões de discriminação (chamados de “filtros”) das imagens de amostras de escrita manual. Filtros em níveis inferiores da rede representam bordas e cantos, enquanto as camadas de nível superior usavam as bordas e cantos para aprender conceitos mais abstratos (como estilo de traço de escrita), que foram usados para classificar as imagens.  

Vamos agora nos concentrar em como isso tudo é aplicado à visão computacional. Nesse contexto, o objetivo de um algoritmo de machine learning é pegar conjuntos de imagens e identificar padrões que podem ser usados para discriminar várias classes ou objetos de imagem (mostrar como se diferem umas das outras). Para se entender a vantagem do deep learning nesse caso, é interessante descrever antes como a visão computacional é implementada sem deep learning. Neste caso,  para cada imagem do dataset usado, é feito um processo chamado extração de características (em inglês, feature extraction), em que a imagem de entrada é quantificada de acordo com um algoritmo específico para tal (chamado de feature extractor ou image descriptor) e retorna um vetor (por exemplo, uma lista de números), que tem o objetivo de quantificar o conteúdo da imagem (veja Figura 6).

feature
Figura 6: Exemplo de quantificação do conteúdo de uma imagem. Fonte: Adrian Rosebrock.

Após esse processo, pode-se usar uma variedade de métodos como “keypoint detectors”, que envolve a detecção simultânea de pessoas e a localização de seus pontos-chave 1 e “local invariant descriptors”, que combina informações de luminância e cor, para salientar regiões de uma imagem. Um método que acho bem interessante é o Histogram of Oriented Gradients (HOG), que é muito bom para detectar objetos em imagens quando o ângulo do ponto de vista (da imagem) não varia drasticamente em relação ao que o computador foi treinado. Pode ser usado em associação a outros métodos.

Recapitulando, em todos esses métodos sem deep learning, um algoritmo é implementado para quantificar e codificar um aspecto específico da imagem (pode ser forma, textura, cor, etc.), que retorna um vetor com a quantificação da imagem (o processo de extração de recursos), que, por sua vez, é usado como entrada para o modelo de machine learning. Em deep learning, usamos uma abordagem diferente e aplicamos as intensidades de pixel brutas como entradas para os modelos. Isso quer dizer que em vez de definir manualmente um conjunto de regras e algoritmos para extrair recursos de uma imagem, esses recursos são aprendidos automaticamente no processo de treinamento do computador. 

Pegando como exemplo as redes neurais convolucionais, citadas anteriormente, o computador tenta “entender” o problema em termos de hierarquia de conceitos. Cada conceito é construído em cima dos outros. Os conceitos nas camadas de nível inferior da rede codificam alguma representação básica do problema, enquanto as camadas de nível superior usam essas camadas básicas para formar conceitos mais abstratos. Esse aprendizado hierárquico permite remover completamente o processo de extração de recursos (definidos à mão) e tratar as CNNs como “aprendizes” de ponta a ponta 2. A Figura 7 mostra a arquitetura completa.

cnn
Figura 7: Aplicação de CNN em visão computacional. Fonte: https://learnopencv.com/wp-content/uploads/2017/11/cnn-schema1.jpg.

Na imagem acima, podemos ver três tipos de camadas, a saber: Camada convolucional, camada de pool e camada totalmente conectada. (Convolutional Layer, Pooling Layer, e Fully Connected Layer). O objetivo principal da camada convolucional é extrair recursos como bordas, curvas, cantos, orientação de gradiente da imagem de entrada. A camada de pool é usada para reduzir o tamanho da representação e acelerar a computação. O pooling é responsável por reduzir o tamanho espacial do recurso “convolido” e diminuir a capacidade computacional necessária para processar os dados. Funciona como se fosse um zip, que reduz o tamanho do arquivo. A diferença é que no processo de pooling, essa redução se dá pela eliminação de informação, o que não é ruim, pois se diminui a possibilidade de overfitting (pense no overfitting como uma espécie de “decoreba” praticada pelo modelo). Por fim, o objetivo da camada totalmente conectada é pegar os resultados do processo de convolução / pooling e usá-los para classificar a imagem em um rótulo.

O “pulo do gato” é definir corretamente o número de camadas e o número de nós em cada camada oculta, já que estes são os dois hiperparâmetros principais que controlam a arquitetura (ou topologia) da rede neural artificial. A maneira mais confiável de configurar esses hiperparâmetros é por meio de experimentação sistemática, com um equipamento de teste robusto. Isso não é algo trivial de se fazer, em especial para iniciantes no campo de machine learning, porque em geral não é possível definir uma maneira analítica de calcular o número ideal de camadas e nós. Existem algumas regras práticas que facilitam o trabalho, mas isso já é assunto para outro texto. 

Ufa! Se você chegou até aqui, parabéns. Sei que um texto extenso, e com um assunto não muito comum como este, não é fácil de se ler. Espero ter lhe ajudado a compreender um pouco mais sobre essa parte importante da inteligência artificial e o método principal que tem sido usado para implementá-la. 

[1] R. Reddy, The challenge of artificial intelligence. in Computer, vol. 29, no. 10, pp. 86-98, Oct. 1996, doi: 10.1109/2.539726.

[2] Fago, J., & Deruelle, C. (1997). Processing of global and local visual information and hemispheric specialization in humans and baboons (Papio papio). Journal of Experimental Psychology: Human Perception and Performance, 23(2), 429–442. https://doi.org/10.1037/0096-1523.23.2.429

[3] Richard Szeliski. 2010. Computer Vision: Algorithms and Applications (1st. ed.). Springer-Verlag, Berlin, Heidelberg.

[4] Alex Krizhevsky, Ilya Sutskever, and Geoffrey E Hinton. 2012. Imagenet classification with deep convolutional neural networks. In Advances in neural information processing systems. 1097–1105.

[5] Eliot, Lance. Say Aloha To Self-Driving Cars As Hawaii Approves Roadway Testing, Though Paradise Not Assured. Forbes, https://www.forbes.com/sites/lanceeliot/2020/09/24/say-aloha-to-self-driving-cars-as-hawaii-approves-roadway-testing-though-paradise-not-assured/. 2020.

[6] Fouhey, David F.; Kuo, Wei-cheng; Efros, Alexei A.; Malik, Jitendra. From Lifestyle Vlogs to Everyday Interactions. arXiv:1712.02310 [cs], december 2017. arXiv.org, http://arxiv.org/abs/1712.02310.

[7] Rosebrock, Adrian. Deep Learning for Computer Vision with Python. 2nd edition. pyimagesearch, 2018.

[8] Rosenblatt, F. The perceptron: A probabilistic model for information storage and organization in the brain. Psychological Review, Vol 65(6), Nov 1958, 386-408.

[9] Minsky, Marvin and Papert, Seymour. Perceptrons: An Introduction to Computational Geometry. Cambridge, MA, USA: MIT Press, 1969.

[10] Ian Goodfellow, Yoshua Bengio and Aaron Courville: Deep Learning (Adaptive Computation and Machine Learning), MIT Press, Cambridge (USA), 2016.

[11] Macêdo, David Lopes de. Enhancing deep learning performance using displaced rectifier linear.

Universidade Federal de Pernambuco. 2017.

[12] LeCun, Y., et al. “Backpropagation Applied to Handwritten Zip Code Recognition”. Neural Computation, vol. 1, no 4, december 1989, p. 541–51.

1 Pontos-chave são a mesma coisa que pontos de interesse.

2 Em um aprendizado ponta-a-ponta, o sistema aprende como um todo. Isso quer dizer que o modelo aprende todas as etapas entre a fase de entrada inicial e o resultado final.

Receba nossos posts GRÁTIS!
Deixe um comentário

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish. Accept Read More