
É difícil encontrar, hoje em dia, qualquer pessoa que não tenha pelo menos escutado os termos inteligência artificial ou aprendizado de máquina. O número de aplicações destas técnicas é enorme e a tendência é que continue crescendo. Mas afinal, como as máquinas aprendem?
Vamos começar com um pouco de história.
Em 1936, no artigo, On Computable Numbers [1], Alan Turing, introduzia os princípios que definem o que conhecemos hoje como computador. Possivelmente, fascinado com o número de possibilidades e o poder de resolver problemas daquele construto que acabara de criar, em 1950, Turing já discutia no artigo, Computing Machinery and Intelligence [2], se computadores seriam capazes de pensar. Esta discussão está fora do escopo deste post mas já neste artigo, Turing discute, de forma ainda um pouco superficial, procedimentos para “ensinar” computadores.
O grande problema quando estamos tentando ensinar um computador é não entendermos em detalhe como nós mesmos aprendemos as coisas. Existe uma vasta literatura na pedagogia sobre como crianças e adultos aprendem, mas os mecanismos físicos, químicos e biológicos deste processo ainda não são conhecidos em detalhe. Ainda assim, algoritmos de aprendizado de máquina existem e funcionam razoavelmente bem. Então, como estes algoritmos funcionam?
Definindo aprendizado
Um algoritmo de aprendizado de máquina existe para cumprir um ou mais objetivos. Assim, o primeiro passo é definir uma função de utilidade, U, que envelopa todos este objetivos de forma que quanto maior U, mais próximo o algoritmo está de cumprir este objetivo. Uma vez que U é definido matematicamente, podemos definir “aprendizado” como um problema de otimização da seguinte forma:

Então temos que encontrar os parâmetros internos, p, do algoritmo de forma a maximizar a função de utilidade, U. Fazendo uma analogia, bastante imprecisa, com o nosso próprio corpo, é como se p definisse como os neurônios no nosso cérebro estão conectados e como eles se comportam dados os estímulos sensoriais, internos e externos, que o nosso corpo recebe.
Com uma definição matemática do problema de aprendizagem, podemos utilizar técnicas de otimização, ou programação matemática, para resolver o problema. Provavelmente, a técnica mais utilizada neste tipo de problema é a técnica de subida do gradiente.
Se você não está interessado na parte matemática, mas achou o assunto interessante, foi um prazer. Dê uma lida no artigo Computing Machinery and Intelligence [2] brilhantemente escrito por Turing e nos vemos no próximo post :D. Se está interessado, siga comigo, está quase acabando 🙂
Aprendendo
O gradiente de uma função U, definido como ∇U, é um vetor que aponta para direção de maior crescimento da função. Ele é composto pelas derivadas parciais da função em relação a cada uma das variáveis. Em outros termos, o gradiente define qual a taxa de variação instantânea da função em relação a cada um dos parâmetros.
Esta informação é extremamente útil, pois assim o algoritmo sabe quais parâmetros devem ser ajustados e como eles devem ser ajustados de forma a maximizar a função de utilidade ∇U.
Neste contexto, aprender significa então executar o seguinte algoritmo:
Dado um conjunto de estímulos, ξ, e um conjunto de parâmetros, p, no tempo t, pt,
- Calcular o gradiente de U em pt
- Atualizar os parâmetros
pt+1 = pt + α∇U(pt)
- Ir para o passo (1) até atingir algum critério de parada
Onde α é conhecido como taxa de aprendizado e define o tamanho do passo a ser dado na direção do gradiente da função de utilidade.
Assim, a cada iteração os parâmetros são ajustados de forma que o valor da função de utilidade fique cada vez maior. Eventualmente, este algoritmo converge para um máximo de U. Note que, em muitos casos, o objetivo deste algoritmo pode ser minimizar alguma medida de erro. Neste caso, basta seguir no sentido oposto do gradiente fazendo a atualização dos parâmetros com a equação abaixo.
pt+1 = pt – α∇U(pt)
Até aqui, tudo parece muito bom. Temos um modelo matemático do que se deseja “aprender” e um algoritmo que executa o “aprendizado”. No entanto, nem tudo são flores. Definir uma função de utilidade adequada pode ser complicado. Além disso, o algoritmo acima pode demorar demais para convergir e ainda ficar preso em máximos locais [3]. Outro problema comum é o chamado overfitting [4], que acontece quando o algoritmo atinge valores altos de utilidade durante o treinamento mas este comportamento não se repete durante o teste.
Existem na literatura, várias maneiras de contornar estes problemas, mas estes são tópicos para próximos posts.
Você sabia que este artigo foi escrito pelo time do TerraLAB? Você sabe como a escassez de profissionais qualificados impacta as empresas de Tecnologia da Informação? Clique aqui para conhecer os desafios desta indústria e como uma parceria com o TerraLAB pode ajudar você e a sua empresa. O TerraLAB é um celeiro de talentos que prepara estudantes para o mercado de trabalho, oferecendo vivências em projetos reais e experiência nos mais modernos processos e ferramentas de desenvolvimento de software. Siga-nos nas redes sociais para saber mais!
Este artigo foi escrito por Prof. Rodrigo Silva e Alan Santandrea, revisado por Luka Menin.
- Referências:
[1] Turing, A. M. (1936). On computable numbers, with an application to the Entscheidungsproblem. J. of Math, 58(345-363), 5.
[2] Turing, A. M. (1950). Computing Machinery and Intelligence. Mind, 59, 433–460.
[3] Local Optimization Versus Global Optimization (machinelearningmastery.com)
[4] Roelofs, R., Fridovich-Keil, S., Miller, J., Shankar, V., Hardt, M., Recht, B., & Schmidt, L. (2019, December). A meta-analysis of overfitting in machine learning. In Proceedings of the 33rd International Conference on Neural Information Processing Systems (pp. 9179-9189).