Aprendizagem de Máquina é Divertido!

A introdução à aprendizagem de máquina mais fácil do mundo

Nota do tradutor: Este post é a tradução de um artigo por Adam Geitgey, de uma série de artigos originalmente em inglês. Leia a série completa original: Part 1, Part 2, Part 3, Part 4, Part 5, Part 6, Part 7 and Part 8!

Você pode ler em português a Parte 1, Parte 2, Parte 3, Parte 4, Parte 5, Parte 6, Parte 7 e Parte 8.

Você já ouviu as pessoas falando sobre aprendizagem de máquina (machine learning) mas tem apenas uma vaga idéia do quê isto significa? Você está cansado de fingir entender as conversa com os colegas de trabalho? Vamos mudar isto!

Este guia é para todos que estejam curiosos sobre aprendizagem de máquina mas que não tem a menor ideia por onde começar. Imagino que haja várias pessoas que tentaram ler o artigo na Wikipédia (ou em inglês), ficaram frustradas e desistiram desejando que alguém apenas lhes desse uma idéia geral sobre o tema. Este artigo é isto.

O objetivo é ser acessível a qualquer um — o que significa que há muitas generalizações. Mas quem se importa? Se este artigo fizer com que alguém fique mais interessado em AM, então, missão cumprida.

O que é Aprendizagem de Máquina?

Aprendizagem de máquina é a ideia de que há algoritmos genéricos que podem dizer algo interessante sobre um conjunto de dados sem que você tenha que escrever nenhum código específico ao problema. Ao invés de escrever código, você alimenta o algoritmo genérico com dados e ele constrói sua própria lógica a partir dos dados.

Por exemplo, um tipo de algoritmo é classificador. Ele pode atribuir dados para diferentes grupos. O mesmo algoritmo de classificação usado para reconhecer caracteres manuscritos pode também ser utilizado para classificar emails em spam e não spam sem ter que mudar nenhuma linha de código. É o mesmo algoritmo, mas quando alimentado com dados de treinamento diferente, cria uma lógica de classificação diferente.

Este algoritmo de aprendizagem de máquina é uma caixa preta que pode ser reutilizado em diferentes problemas de classificação

“Aprendizagem de Máquina” é um termo genérico que cobre vários tipos destes algoritmos genéricos.

Dois tipos de algoritmos de aprendizagem de máquina

Há duas categorias principais de algoritmos de aprendizagem de máquina: aprendizagem supervisionado e aprendizagem não supervisionado. A diferença é simples, mas realmente importante.

Aprendizagem Supervisionada

Digamos que você é um corretor de imóveis. Seu negócio está em plena expansão, então você contrata vários trainees para te ajudar. Mas há um problema. Com uma olhada rápida, você pode ter uma boa idéia do valor de um imóvel. Já os seus trainees não tem a sua experiência, de modo que ele não sabem como avaliar os imóveis.

Para ajudar os seus trainees (e talvez tirar umas férias), você decide escrever um aplicativo para estimar o valor de um imóvel na sua área levando em conta a área total, o bairro, etc., e qual o preço de venda de imóveis similares.

Assim, você anota informações de vendas de imóveis na sua cidade por três meses. Para cada imóvel você anota vários detalhes: número de quartos, tamanho em metros quadrados, bairro, etc. Mas principalmente, você anota o preço final de venda.

Estes são nossos “dados de treinamento”

Usando estes dados de treinamento, queremo criar um programa que possa estimar o valor de qualquer outro imóvel na sua vizinhança.

Queremos utilizar os dados de treinamento para predizer os preços de outros imóveis.

Isto é chamado aprendizagem supervisionada. Você sabia o valor de venda de cada imóvel, então você sabia a resposta para o problema e pode fazer engenharia revesa para descobrir a lógica utilizada.

Para construir seu aplicativo, você alimenta o seu algoritmo de aprendizagem de máquina com os dados de treinamento sobre cada venda. O algoritmo tenta descobrir qual a matemática que deve ser feita para que os números façam sentido.

É como ter o gabarito para um teste de matemática com todos os simbolos de operações aritméticas apagados.

Essa não! Um aluno travesso apagou os símbolos aritiméticos do gabarito de respostas do professor!

A partir disto, você consegue descobrir quais problemas matemáticos estavam no teste? Você sabe que tem que “fazer alguma coisa” com os números à esquerda para chegar na resposta à direita.

Em aprendizagem supervisionada você deixa o computador descobrir o relacionamento pra você. E uma vez que você saiba a matemática necessária para resolver este conjunto específico de problemas, você poderá responder qualquer outro problema do mesmo tipo!

Aprendizagem não supervisionada

Vamos retomar o exemplo original com o corretor de imóveis. E se você não soubesse o preço de venda de cada imóvel? Mesmo que você só saiba a área total, a localização, etc., ainda assim você pode fazer coisas muito interessantes. Isto é chamado aprendizagem não supervisionada.

Mesmo que vovê não esteja tentando predizer um número desconhecido (como o preço), você ainda pode fazer coisas interessantes com aprendizagem de máquina

É como se alguém lhe mostrasse uma lista de números em uma folha de papel e dissesse “Eu não sei o que estes números significam, mas talvez você possa descobrir se há algum padrão ou agrupamento, ou alguma coisa — boa sorte!

Então, o que se pode fazer com estes dados? Para começo de conversa, você pode ter um algoritmo que identifica segmentos de mercados nos seus dados. Talvez você iria descobrir que compradores de imóveis próximo da universidade local preferem casas menores mas com muitos quartos, já compradores de imóveis em condomínios preferem casas com 3 quartos que tenham muita área construida. Sabendo sobre estes tipos diferentes de clientes pode ajudar a direcionar seus esforços de marketing.

Outra coisa legal que você poderia fazer automaticamente é identificar casas fora do padrão, que são muito diferentes de todas as outras. Talvez estas casas fora do padrão sejam mansões gigantes e você pode focar os seus melhores vendedores nestas áreas, pois elas rendem comissões maiores.

Aprendizado supervisionado é o foco do resto deste post, mas não é porque aprendizado não supervisionado seja menos útil ou menos interessante. Na realidade, aprendizado não supervisionado está se tornando cada vez mais importante à medida que os algoritmos estão ficando melhores, já que se pode utilizá-los sem ter que rotular os dados com respostas corretas.

Nota: há muitos outros tipos de algoritmos de aprendizagem de máquina. Mas este aqui é um bom lugar para começar.

Legal, mas ser capaz de estimar o preço de uma casa realmente conta como “aprendizagem”?

Como humano, seu cérebro pode abordar quase qualquer situação e aprender como lidar com aquela situação sem instruções explícitas. Se você vender casas por muito tempo, você vai desenvolver um “instinto” para o preço correto de uma casa, a melhor estratégia de venda, o tipo de cliente que estaria interessado, etc. O objetivo da área de pesquisa em I.A. Forte é ser capaz de replicar esta habilidade em computadores.

Algoritmos atuais de aprendizagem de máquina ainda não são tão bons assim. Eles só funcionam quando focados em um problema muito específico e limitado. Talvez uma definição melhor para “aprendizagem” neste caso seja “descobrindo uma equação para resolver um problema específico baseado em alguns dados de exemplo”.

Infelizmente “maquinas descobrindo uma equação para resolver um problema específico baseado em alguns dados de exemplo” não é um nome muito bom. Assim, acabamos ficando com “aprendizagem de máquina”.

Claro que se você estiver lendo isto daqui a 50 anos e nós tivermos descoberto algoritmos para IA Forte, então este post inteiro pode parecer um pouco obsoleto. Talvez seja hora de dar uma pausa na leitura e pedir para seu robô preparar um sandwich, humano do futuro.

Hora de Programar!

Então, como escrever o programa que estima o valor de um imóvel como no exemplo acima? Pense sobre isto por um momento antes de você continuar a leitura.

Se você não sabia nada sobre aprendizagem de máquina, você provavelmente tentou escrever algumas regras para estimar o preço, mais ou menos assim:

def preco_venda_imovel_estimado(num_quartos, metros, bairro):
preco = 0
# Em meu bairro o preço custa $200 por metro quadrado
preco_por_metro = 200
if bairro== "hipsterton":
# mas alguns bairros são um pouco mais caros
preco_por_metro = 400
elif bairro== "skid row":
# e outros bairros custam menos
preco_por_metro = 100
# começe com o preço base estimado a partir da área do imóvel 
preco = preco_por_metro * metros
# depois ajuste a estimativa de acordo com o número de quartos 
if num_quartos == 0:
# Quitinetes custam bem pouco
preco = preco — 20000
else:
# imoveis com mais quartos geralmente são mais valorizados
preco = preco + (num_of_bedrooms * 1000)
return preco

Se você brincar com este código por horas e horas, você pode acabar produzindo algo que funcione. Mas seu programa nunca será perfeito e vai ser difícil de fazer manutenção quando houver mudança de preços.

Não seria melhor se o computador pudesse descobrir como implementar a função para você? Quem se importa com os detalhes da função, desde que ela retorne o número correto:

def preco_venda_imovel_estimado(num_quartos, metros, bairro):
preco = <computador, faça a matemática pra mim, por favor>
return preco

Um modo de ver este problema é pensar que o preço é um delicioso ensopado e os ingredientes são o número de quartos, o metro quadrado e o bairro. Se você pode descobrir o quanto cada ingrediente impacta no preço final, talvez haja uma proporção exata de ingredientes para incluir na composição final do preço.

Isto iria reduzir sua função original (com todos aqueles ifs e elses loucos) para algo realmente simples, tal como:

def preco_venda_imovel_estimado(num_quartos, metros, bairro):
preco = 0
# um pouco disso 
preco += num_quartos * .841231951398213
# um bocado daquilo
preco += metros * 1231.1231231
# talvez uma pitada disto aqui
preco += bairro * 2.3242341421
# e finalmente, um pouco de sal para dar um tempero
preco += 201.23432095
return preco

Note os números mágicos em negrito, .841231951398213, 1231.1231231, 2.3242341421, and 201.23432095. Este são os pesos. Se pudéssemos descobrir pesos perfeitos que funcionassem para cada imóvel, nossa função poderia predizer preços de imóveis!

Uma maneira não muito inteligente de descobrir os melhores pesos poderia ser algo assim:

Passo 1:

Começe com cada peso igual a 1.0:

def preco_venda_imovel_estimado(num_quartos, metros, bairro):
preco = 0
# um pouco disso 
preco += num_quartos * 1.0
# um bocado daquilo
preco += metros * 1.0
# talvez uma pitada disto aqui
preco += bairro * 1.0
# e finalmente, um pouco de sal para dar um tempero
preco += 1.0
return preco

Passo 2:

Teste cada imóvel que você conheçe com esta função e veja quão errada a função está ao advinhar o preço correto de cada imóvel:

Use sua função para predizer o preço de venda de cada casa.

Por exemplo, se o primeiro imóvel foi realmente vendido por $250.000, mas sua função estimou o preço de venda em $178.000, você errou por $72.000 somente neste imóvel.

Agora some o quadrado do erro para cada imóvel que você tem registrado. Digamos que você tem registradas 500 vendas de imóveis e o quadrado do erro de sua função em cada imóvel dá um total geral de $86.123.373,00. Isto representa quão errada está sua função atualmente.

Agora, divida esta soma por 500 para termos uma média do erro de cada imóvel. Vamos chamar esta média de custo da sua função.

Se você pudesse zerar este custo apenas testando valores diferentes para os pesos, sua função seria perfeita. Isto significaria que sua função teria predito perfeitamente cada preço de venda de imóvel baseado nos seus registros. Então, este é o nosso objetivo: minimizar o custo o tanto que for possível apenas tentando pesos diferentes.

Passo 3:

Repita o Passo 2 várias vezes com cada combinação possível de pesos. Qualquer combinação de pesos que faça o custo ser próximo de zero pode ser utilizada. Se você encontrar pesos que funcionem, você resolveu o problema.

Hora de Pirar

Tudo muito simples, não? Bem, pense sobre o que você acaba de fazer. Você pegou alguns dados, e usou eles em três passos bem genéricos e realmente simples e produziu uma função que pode chutar o preço de qualquer imóvel em seu bairro. Cuidado Zap Imóveis!

Mas há mais alguns fatos que vão te fazer pirar a cabeça:

  1. Pesquisa em muitas áreas (como linguística/tradução) nos últimos 40 anos mostraram que este algoritmo genérico de aprendizagem que “mexe o ensopado de números” (uma frase que acabei de inventar) tem performance melhor que outras abordagens onde pessoas reais tentam criar suas próprias regras explícitas. A abordagem “burra” de aprendizagem de máquina acaba sendo melhor que os especialistas humanos.
  2. A função que você criou é totalmente burra. Ela nem mesmo sabe o quê são “metros” ou “quartos”. Tudo que ela sabe é que ela tem que misturar uma quantidade destes números para chegar a resposta correta.
  3. É bem provável que você não tenha ideia de porque um conjunto particular de pesos funciona. Assim, você acabou de escrever uma função que você realmente não entende, mas que você comprova que funciona.
  4. Imagine que ao invés de receber parâmetros como “metros” e “num_quartos”, sua função de predição recebesse um vetor de números. Digamos que cada número representasse o brilho de um pixel em uma imagem capturada por uma camera instalada no topo do seu carro. Agora, digamos que ao invés de produzir uma saída predizendo o “preço” a sua função faça predições do “angulos_para_girar_o_volante”. Você acaba de criar uma função que pode dirigir seu carro por si mesma!

Muito louco, não?

E quanto aquela parte de “tentar todos os números” no Passo 3?

Tudo bem, é claro que você não pode simplemente tentar todas as combinações de todos os possíveis pesos para encontrar uma combinação que funcione melhor. Isto iria literalmente durar para sempre, pois você teria novos números para tentar.

Para evitar isto, matemáticos inventaram várias maneiras inteligentes para encontrar rapidamente bons valores para estes pesos sem ter que tentar uma quantidade muito grande deles. Aqui está uma maneira:

Primeiro, escreva uma equação simples que represente o Passo 2 acima:

Esta é sua função de custo.

Agora, vamos reescrever exatamente a mesma equação, mas usando um monte de jargão matemático de aprendizagem de máquina (que você pode ignorar por enquanto):

θ é o que representa seus pessos atuais. J(θ) significa a ‘função de custo com os pesos atuais’.

Esta equação representa quão errado está sua função de estimativa de preço com os pesos atuais.

Se desenharmos um gráfico desta função de custo para todos os valores possível dos nossos pesos para num_quartos e metros, nós teríamos um gráfico que poderia ser parecido com o seguinte:

O gráfico da função parece uma tigela. O eixo vertical representa o custo.

Neste gráfico, o ponto mínimo em azul é onde o custo é menor — portanto, é onde nossa função é menos errada. Os pontos máximos são onde nós estamos mais errados. Então, se pudermos encontrar os pesos que nos levam para o menor ponto neste gráfico, nós teremos nossa reposta!

(1.0,1.0) é onde estamos e queremos ir para o ponto mínimo do gráfico.

Assim, precisamos apenas ajustar os pesos “andando ladeira abaixo” neste gráfico em direção ao ponto mínimo. Se formos fazendo pequenos ajustes nos nosso pesos que estejam sempre se movendo em direção ao menor ponto, iremos chegar lá sem ter que tentar muitos pesos diferentes.

Se você lembra alguma coisa de Cálculo, vai se lembrar que se você tomar a derivada de uma função, ela informa o ângulo da tangente da função em um dado ponto. Em outras palavras, a derivada nos informa qual a direção aponta para o mínimo em um determinado ponto no nosso gráfico. Podemos utilizar este conhecimento para percorrer o gráfico de maneira descendente.

Então, se calcularmos a derivada parcial da função de custo com relação a cada peso, poderemos então subtrair este valor de cada peso. Isto irá nos levar um passo mais próximo do ponto mínimo do gráfico. Continue fazendo isto e iremos acabar encontrando o ponto mínimo onde teremos os melhores valores para os pesos. (Se isto não faz sentido, não se preocupe e continue lendo).

Isto foi um resumo rápido de uma estratégia chamada descida do gradiente em lote para encontrar os melhores pesos para nossa função. Não tenha medo de ir à fundo neste tema se você está interessado em aprender os detalhes.

Quando se usa uma biblioteca de aprendizagem de máquina para resolver um problema real, tudo isto será feito para você. Mas ainda assim é útil que se tenha um boa ideia do que está acontecendo.

O que mais você convenientemente omitiu?

O algoritmo de três passos que eu descrevi é chamado regressão linear multivariáveis. Você está estimando a equação da reta que passa por todos os seus registros de imóveis. Depois, você está usando esta equação para chutar preços de imóveis que você nunca viu antes baseado no local da linha onde o imóvel está localizado. É uma ideia realmente poderosa e você pode resolver problemas “reais” com ela.

Mas enquanto a abordagem que mostrei pode funcionar em casos simples, ela não funcionará em todos os casos. Uma razão para isto é que preços de imóveis não são sempre simples o suficiente para seguir uma linha contínua.

Felizmente, há várias maneiras de lidar com isto. Há vários outros algoritmos de aprendizagem de máquina que podem ser aplicados a dados não lineares (tais como redes neuronais ou SVMs com kernels). Há ainda maneiras de utilizar regressão linear mais inteligente que permite ajustar linhas complicadas. Em todos os casos, a mesma ideia basica de encontrar os melhores pesos ainda se aplica.

Além disso, eu ignorei a ideia de sobreajuste (overfitting). É fácil encontrar um conjunto de pesos que funciona perfeitamente para predizer os preços de imóveis no conjunto de registro original mas que nunca irá funcionar para novos imóveis que não estavam no conjunto original. Mas há maneiras de lidar com isto (tais como regularização e usar um conjunto dados para validação cruzada). Aprender como tratar estas questões é fundamental para que se possa aplicar aprendizagem de máquina com sucesso.

Em outras palavras, o conceito básico é bem simples mas é necessário habilidade e experiencia para aplicar aprendizagem de máquina e ter resultados úteis. Entretanto, é uma habilidade que qualquer desenvolvedor pode aprender!

Aprendizagem de máquina é mágica?

Assim que você começar a ver como é fácil aplicar as técnicas de aprendizagem de máquina à problemas que parecem difíceis (como reconhecimento de escrita), você comecará a pensar que você pode utilizar aprendizagem de máquina para resolver qualquer problema e que você terá uma resposta desque tenha dados suficiente. É só alimentar o computador com os dados e observá-lo magicamente descobrir a equação que modela os dados!

É importante lembrar, contudo, que aprendizagem de máquina só funciona se o problema realmente tiver solução a partir dos dados disponíveis. Por exemplo, se você construir um modelo que prediz os preços de imóveis baseado no tipo de vasos de plantas em cada imóvel, ele não irá funcionar. Não existe relação entre o tipo de vasos de plantas na casa e o preço de venda do imóvel. Então, não importa quantas vezes ele tente, o computador não poderar encontar um relacionamento entre os dois.

Só se pode modelar relacionamentos que realmente existam.

Portanto, lembre-se que se um expert humano não pode utilizar os dados para resolver o problema manualmente, o computador provavelmente também não será capaz. Ao invés disso, foque nos problemas que são solucionáveis por humanos, mas que seriam seriam resolvidos mais rapidamente por um computador.

Como aprender mais sobre Aprendizagem de Máquina

Para mim, o principal problema com aprendizagem de máquina atualmente é que se trata de um tema majoritariamente acadêmico e de grupos de pesquisa corporativos. Não há muito material disponível, que seja fácil de entender, para pessoas que queiram ter uma visão geral sem se tornar necessariamente experts. Mas está ficando um pouco melhor a cada dia.

Se você quiser testar o que você aprendeu neste artigo, o autor preparou um curso que te guia por todos os passos deste artigo, incluindo escrever todo o código. Experimente!

Se você quiser ir mais a fundo, o curso de Aprendizagem de Máquina de Andrew Ng, de graça no Coursera, é um excelente próximo passo. Eu o recomendo fortemente. O curso é compreensível a todos que tenham uma graduação em Ciência da Computação e que ainda lembram um pouco de matemática.

Você também pode brincar com uma vasta quantidade de algoritmos de aprendizagem de máquina fazendo download e instalando SciKit-Learn. O SciKit-Learn é uma biblioteca em python que implementa uma versão “black box” dos algoritmos de aprendizagem de máquina mais comuns.


Nota do autor: Se você gostou deste artigo, por favor considere assinar a lista de e-mail “Machine Learning is Fun!”. Só irei enviar email quando houver algo novo e incrivel para compartilhar. É a melhor maneira de ser informado quando eu escrever mais artigos iguais a este.

Por favor, também veja a versão completa deste artigo. Ele mostra tudo deste artigo em muito mais detalhes, incluindo como escrever o código real em Python. Você pode obter um teste de 30 dias gratuito para assistir ao curso se você se inscrever com este link.

Você pode me seguir no Twitter at @ageitgey, enviar email diretamente ou ainda me encontrar no linkedin. Eu adoraria saber se posso ajudar a você ou à sua equipe com aprendizagem de máquina.

Nota do tradutor: Agora, continue com Aprendizagem de Máquina é Divertido Parte 2!

Há também uma tradução em português deste artigo pela equipe do TCU (link).