Open In Colab

!pip install -Uqqq matplotlib

Dados

Dados de número de vendedores e quantidade vendida (média diária) para 10 lojas de uma franquia

num_vendedores = [8, 20, 26, 2, 8, 20, 22, 12, 6, 16]
num_de_vendas = [88, 169, 202, 58, 118, 157, 149, 117, 105, 137]
import matplotlib.pyplot as plt
plt.scatter(num_vendedores, num_de_vendas);

Como você fará no dia a dia

import numpy as np
from sklearn.linear_model import LinearRegression
x = np.array(num_vendedores)
y = np.array(num_de_vendas)
reg = LinearRegression().fit(x.reshape((-1,1)), y)
a, b = reg.coef_.item(), reg.intercept_
a, b
(5.000000000000001, 59.999999999999986)

Ou ainda usando apenas o numpy

a, b = np.polyfit(x, y, 1)
a, b
(4.999999999999999, 60.000000000000014)

Visualizando a regressão linear

plt.scatter(num_vendedores, num_de_vendas);
plt.axline((0, b), slope = a, color = 'red', linestyle = '--');

Predição (inferência)

nova_loja_num_vendedores = 14
nova_loja_venda_esperada = a * nova_loja_num_vendedores + b
nova_loja_venda_esperada
130.0
plt.scatter(num_vendedores, num_de_vendas);
plt.axline((0, b), slope = a, color = 'red', linestyle = '--');
plt.scatter(nova_loja_num_vendedores, nova_loja_venda_esperada, color = 'red');

Implementando (e entendendo) um modelo de regressão linear

import torch
x = torch.tensor(num_vendedores)
y = torch.tensor(num_de_vendas)

1 - Inicialização

a = torch.randn(1).requires_grad_()
b = torch.randn(1).requires_grad_()
a, b
(tensor([-1.4139], requires_grad=True), tensor([1.0566], requires_grad=True))

2 - Predição

y_pred = a * x + b
y_pred
tensor([ -6.4832, -18.1523, -23.9869,  -0.6486,  -6.4832, -18.1523, -20.0972,
        -10.3729,  -4.5383, -14.2626], grad_fn=<AddBackward0>)
plt.scatter(x, y);
plt.scatter(x, y_pred.detach(), color = 'red');
plt.axline((0, b.item()), slope = a.item(), color = 'red', linestyle = '--');

3 - Perda (erro)

erro = y - y_pred
erro
tensor([ 94.4832, 187.1523, 225.9869,  58.6486, 124.4832, 175.1523, 169.0972,
        127.3729, 109.5383, 151.2626], grad_fn=<SubBackward0>)
rmse = (erro**2).mean()**0.5
rmse
tensor(149.7778, grad_fn=<PowBackward0>)

4 - Gradiente (🧙 Mate-Mágica!! ✨)

rmse.backward()
a.grad, b.grad
(tensor([-15.9815]), tensor([-1.1920]))

Step (passo)

a.data = a.data - a.grad
b.data = b.data - b.grad
a.grad.zero_()
b.grad.zero_();

Repetir n-vezes

historico_rmse = []
## Hiperparâmetros
n_epoch = 10000
lr = 0.05
## Inicialização
a = torch.randn(1).requires_grad_()
b = torch.randn(1).requires_grad_()
## Otimização
for epoch in range(n_epoch):
    ## Predição
    y_pred = a * x + b
    ## Calcula perda (loss)
    erro = y - y_pred
    rmse = (erro**2).mean()**0.5
    if epoch % 1000 == 0:
        print(f'RMSE: {rmse.item()}')
    historico_rmse.append(rmse.item())
    ## Calcula gradiente
    rmse.backward()
    ## Step
    a.data = a.data - lr * a.grad
    b.data = b.data - lr * b.grad
    a.grad.zero_()
    b.grad.zero_()
RMSE: 142.61758422851562
RMSE: 21.743059158325195
RMSE: 15.713376998901367
RMSE: 13.123400688171387
RMSE: 12.502219200134277
RMSE: 12.391326904296875
RMSE: 12.372918128967285
RMSE: 12.369906425476074
RMSE: 12.36941146850586
RMSE: 12.369332313537598
plt.scatter(x, y);
plt.axline((0, b.item()), slope = a.item(), color = 'red', linestyle = '--');
a, b
(tensor([5.0009], requires_grad=True), tensor([59.9831], requires_grad=True))
plt.plot(historico_rmse[:100]);