Criando o modelo de aprendizado de máquina mais simples do mundo
Me siga no X | Me siga no LinkedIn | Apoie a Newsletter | Solicite uma consultoria
O termo “modelo” no contexto de aprendizado de máquina é recorrentemente utilizado para indicar a utilização dos algoritmos em um conjunto de dados, empregados em tarefas de classificação ou predições, por exemplo.
Mas o que seria esse tal “modelo”?
Suponha por um instante que você quer similar o estudo de Galileu, em que ele investigou quanto tempo demoraria a trajetória de duas bolas (com o mesmo volume mas diferente massas) que foram lançadas de diferentes andares da torre de Pisa, até alcançar o chão.
Se você for um experimentalista, talvez sua primeira tentativa seria subir na torre de Pisa e jogar as duas bolas, várias vezes, de cada um dos 8 andares da torre. Ao final desse dia de trabalho, você potencialmente chegaria a mesma conclusão que Galileu, que observou que o tempo de descida das bolas é independente da suas massas. Se fizéssemos um gráfico das anotações dos tempos de descida da bola por andar, talvez chegássemos em algo parecido com a figura abaixo.
Com a imagem, fica fácil entender o padrão de descida nos dados coletados. Esse é o benefício e uma limitação de estudos empíricos: eles ajudam a entender relações e padrões nos dados que temos em mãos, mas pouco ajudam sobre os dados que não conhecemos.
Suponha agora que você quer saber qual o tempo de descida da bola no nono andar?
Com os dados que temos em mão, podemos dar um chute matemático. Talvez 4.2s? Ou talvez 4.4s? Esse chute matemático é exatamente o nosso modelo.
Por conta do tipo da tarefa (predição do tempo que de descida de uma bola), o modelo que criamos é muito simples, e tem aparente bom desempenho. No entanto, os modelos podem rapidamente crescer em complexidade, com diversos parâmetros de configuração (o modelo do ChatGPT, por exemplo, tem centenas de bilhões de parâmetros de configuração).
Colocando em contexto: um modelo de aprendizado de máquina é uma representação matemática que foi treinada em um conjunto de dados fornecidos como entrada para reconhecer certos tipos de padrões.
Generalizando um pouco mais, um modelo de aprendizado de aprendizado de máquina é a soma de um algoritmo, que recebe conjunto de dados, para encontrar certos tipos de padrão.
Criando nosso primeiro modelo
Agora que sabemos o que são modelos e pra que servem, vamos implementar nosso primeiro modelo de aprendizado de máquina (o mais simples do mundo!).
Para iniciar, precisamos instalar a biblioteca sklearn, que é uma das mais populares no universo de programação científica em Python. Essa biblioteca conta com a implementação de diversos algoritmos de aprendizado de máquina. Nossa primeira tarefa é saber qual algoritmo faz sentido utilizar. Para responder, vamos primeiro olhar os nossos dados.
andar1 = [1] # altura em metros
andar2 = [2]
andar3 = [3]
andar4 = [4]
andar5 = [5]
andar6 = [6]
andar7 = [7]
andar8 = [8]
dados = [andar1, andar2, andar3, andar4, andar5, andar6, andar7, andar8]
velocidade = [1, 1.5, 2, 2.3, 2.9, 3.3, 3.6, 3.9] # em segundos
Nossos dados, representados pela variável dados
podem ser entendidos como um vetor de duas dimensões, em que cada item de dado representa a altura de cada andar da torre. A variável velocidade
, por outro lado, indica o tempo (em segundos) em que cada bola demoraria para chegar ao chão.
Como podemos perceber a variável dados
armazena elementos do tipo inteiro, enquanto que a variável velocidade
armazena elementos do tipo float. Essa é uma decisão importante.
Em aprendizado de máquina, dizemos que tipos de dados como inteiros, strings ou booleanos são dados discretos (ou categóricos), ou seja, podem ser contados, categorizados ou enumerados, separados um do outro (sem assumir valores intermediários). Dados contínuos, por outro lado, assumem valores intermediários, como 0.5 ou 1.5.
Por exemplo, a quantidade de filhos que uma pessoa tem é um dado discreto, pois os possíveis valores são inteiros (0, 1, 2, 3…), e não valores intermediários, como 0.5 ou 1.5.
Os modelos de aprendizado de máquina podem ser classificados em diferentes categorias. Uma das formas de categorização é com base na natureza dos dados, pois há algoritmos que trabalham melhor (ou somente) com dados discretos e algoritmos que lidam melhor com dados contínuos.
Como nossa fonte de dados é de dados discretos (variável dados
), utilizaremos uma Regressão Linear. Para aprofundar um pouco mais, há vários textos que técnicos e científicos que descrevem como funciona essa técnica, como este aqui. Mas, em resumo, uma regressão linear simples tenta traçar uma relação entre duas variáveis; no nosso caso, essas variáveis são: andar e velocidade.
A biblioteca sklearn já conta com uma implementação desse algoritmo, em uma classe chamada LinearRegression
.
from sklearn.linear_model import LinearRegression
modelo = LinearRegression()
Agora que já temos o algoritmo (instanciado na variável modelo
) e nossa fonte de dados (armazenada na variável dados
), precisamos agora treinar nosso algoritmo utilizando nosso conjunto de dados.
O processo de treino existe para que nosso modelo possa se adequar aos dados disponíveis. Assim, capacitamos nosso modelo para trabalhar em novos conjuntos de dados. O método fit()
que existe na classe LinearRegression
é responsável pela etapa de treino. O objetivo do fit()
é encontrar uma reta que melhor se ajuste aos dados. Para isso, devemos passar a variável dados
, bem como a velocidade
.
modelo = LinearRegression()
modelo.fit(dados, velocidade)
Depois de treinar o modelo, nosso último passo é testa-lo em um novo conjunto de dados. Esse teste serve para testar a generalização do modelo, isto é, avaliar como nosso modelo se comporta quando são fornecidos dados até então desconhecidos. Para testar o modelo, usamos o método predict
, também implementado na classe LinearRegression
.
modelo.predict([[9]])
# resultado: array([4.45357143])
Perceba que passamos como parâmetro uma matriz, em vez de um único valor. Isso acontece pois podemos realizar múltiplas previsões simultaneamente.
O método predict
retorna um array([4.45357143])
, em que seu único elemento é a predição do valor da velocidade no andar desconhecido (9, no caso).
Sabendo que a velocidade do último andar conhecido é 3.9s, parece bem razoável a velocidade do andar desconhecido seja 4.4s. Podemos testar com outros valores.
modelo.predict([[9, 10, 15, 20, 50]])
# resultado: array([ 4.45357143, 4.87380952, 6.975, 9.07619048, 21.68333333])
A princípio, os resultados continuam fazendo sentido, mas ficou mais difícil avaliar por conta da diferença de grandeza dos dados. Se plotarmos a figura com o tempo dos andares conhecidos e dos andares desconhecidos, teríamos algo como:
Olhando para o gráfico, parece fazer sentido que o tempo de descida das bolas aumenta (quase que linearmente) a media que aumentamos os andares. Nesse caso, dizemos que o nosso modelo teve um bom desempenho (ou boa performance).
Mas perceba que estamos avaliando a performance do modelo com base no nosso próprio entendimento. Será que não existem abordagens mais rigorosas para testar o desempenho de um modelo?
Existem várias. Mas isso é assunto para outro texto de blog :-)
O código completo do exemplo acima está disponível neste link, licenciado como MIT.