Pular para conteúdo

Lista 14 · Regressão linear

Acompanha o capítulo 14. A reta que erra menos, pelas equações normais; o \(R^2\); e o que os resíduos contam.

Abrir no Colab

Baixar o caderno

Como esta lista funciona

Abra o caderno no Colab, escreva a sua solução no lugar do # TODO e rode a célula de teste logo abaixo. Ela mesma diz o que passou e o que falhou — você não precisa esperar correção de ninguém.

O código de cada exercício também está aqui embaixo, caso você prefira colar num editor local. Os testes comparam números com tolerância.

Exercícios marcados com ✏️ são à mão, no papel, com 4 casas decimais — como na parte em papel das avaliações.

Exercício 01

✏️ À mão. Ajuste uma reta aos pontos \((1, 2)\), \((2, 3)\), \((3, 5)\), \((4, 6)\).

a) Calcule \(n\), \(\sum x_i\), \(\sum x_i^2\), \(\sum y_i\) e \(\sum x_i y_i\).

b) Monte e resolva as equações normais.

c) Calcule os resíduos e o \(R^2\).

Exercício 02

Escreva reta_minimos_quadrados(x, y), que monta as equações normais, resolve com np.linalg.solve e devolve a tupla (a0, a1). Converta x e y com np.array (eles podem chegar como listas).

reta_minimos_quadrados([1, 2, 3, 4], [2, 3, 5, 6])    # -> (0.5, 1.4)
import numpy as np


def reta_minimos_quadrados(x, y):
    """(a0, a1) da reta y = a0 + a1 x, pelas equações normais."""
    x = np.array(x)
    y = np.array(y)
    # TODO: a matriz 2 x 2 das somas, o lado direito, np.linalg.solve
    pass


# --- testes (não altere) ---
r = reta_minimos_quadrados([1, 2, 3, 4], [2, 3, 5, 6])
assert r is not None, "faltou o return?"
assert abs(r[0] - 0.5) < 1e-12 and abs(r[1] - 1.4) < 1e-12, f"veio {r}"
r = reta_minimos_quadrados([0, 1, 2], [5, 7, 9])
assert abs(r[0] - 5) < 1e-12 and abs(r[1] - 2) < 1e-12, "pontos em cima de uma reta: ela mesma"
print("Exercício 02: todos os testes passaram!")

Exercício 03

Escreva r_quadrado(x, y, a0, a1):

\[ R^2 = 1 - \frac{\sum (y_i - a_0 - a_1 x_i)^2}{\sum (y_i - \bar y)^2}. \]
import numpy as np


def r_quadrado(x, y, a0, a1):
    """Coeficiente de determinação da reta a0 + a1 x nos dados."""
    x = np.array(x)
    y = np.array(y)
    # TODO: os resíduos, as duas somas de quadrados (use np.mean) e a fórmula
    pass


# --- testes (não altere) ---
assert abs(r_quadrado([1, 2, 3, 4], [2, 3, 5, 6], 0.5, 1.4) - 0.98) < 1e-12
assert abs(r_quadrado([0, 1, 2], [5, 7, 9], 5, 2) - 1) < 1e-12, "reta perfeita"
assert abs(r_quadrado([0, 1, 2], [1, 3, 2], 2, 0)) < 1e-12, "a reta da média explica zero"
print("Exercício 03: todos os testes passaram!")

Exercício 04

Instrumentação — calibrar um sensor. O conversor analógico-digital de um sensor de temperatura dá números de 0 a 4095. Para calibrá-lo, ele foi comparado com um termômetro de referência:

leitura 512 1024 1536 2048 2560 3072
referência (°C) 4,8 15,1 25,3 34,6 45,2 55,0

Escreva leitura_para_temperatura(leitura), que ajusta a reta de calibração com a reta_minimos_quadrados (já escrita) e converte uma leitura em °C.

leitura_para_temperatura(1800)    # -> ≈ 30.16
import numpy as np


def reta_minimos_quadrados(x, y):
    """JÁ ESCRITA."""
    x = np.array(x)
    y = np.array(y)
    n = len(x)
    A = np.array([[n, np.sum(x)], [np.sum(x), np.sum(x**2)]])
    b = np.array([np.sum(y), np.sum(x * y)])
    a = np.linalg.solve(A, b)
    return (a[0], a[1])


def leitura_para_temperatura(leitura):
    """Temperatura (°C) de uma leitura do conversor, pela reta de calibração."""
    leituras = [512, 1024, 1536, 2048, 2560, 3072]
    referencia = [4.8, 15.1, 25.3, 34.6, 45.2, 55.0]
    # TODO: ajuste a reta e aplique-a à leitura
    pass


# --- testes (não altere) ---
assert abs(leitura_para_temperatura(1800) - 30.156517857142855) < 1e-9
assert abs(leitura_para_temperatura(0) - -5.059999999999984) < 1e-9, "o intercepto"
print("Exercício 04: todos os testes passaram!")

Exercício 05

Estatística — a correlação. O coeficiente de Pearson mede o quanto dois dados andam juntos em linha reta: \(+1\) (sobem juntos, exatamente), \(-1\) (um sobe, o outro desce) e \(0\) (nada a ver):

\[ r = \frac{\sum (x_i - \bar x)(y_i - \bar y)}{\sqrt{\sum (x_i - \bar x)^2 \,\sum (y_i - \bar y)^2}}. \]

Escreva correlacao(x, y). Para uma reta de mínimos quadrados, \(r^2 = R^2\): confira com os pontos do ex01.

import numpy as np


def correlacao(x, y):
    """Coeficiente de correlação de Pearson entre x e y (de -1 a 1)."""
    x = np.array(x)
    y = np.array(y)
    # TODO: os desvios em relação à média e a fórmula
    pass


# --- testes (não altere) ---
assert abs(correlacao([1, 2, 3, 4], [2, 3, 5, 6])**2 - 0.98) < 1e-12, "r² = R²"
assert abs(correlacao([1, 2, 3], [6, 4, 2]) - (-1)) < 1e-12, "uma desce quando a outra sobe"
assert abs(correlacao([1, 2, 3, 4], [1, -1, -1, 1])) < 1e-12, "sem relação linear"
print("Exercício 05: todos os testes passaram!")

Exercício 06

Educação — prever sem extrapolar. Numa turma, as horas de estudo semanais e as notas foram: horas [2, 4, 5, 6, 8, 9, 10, 12]; notas [4.1, 5.0, 5.6, 6.3, 7.0, 7.9, 8.2, 9.1]. Escreva previsao_nota(horas), que ajusta a reta (a reta_minimos_quadrados já está escrita) e devolve a nota prevista — mas devolve None se horas estiver fora da faixa observada (de 2 a 12 horas).

previsao_nota(7)     # -> ≈ 6.65
previsao_nota(40)    # -> None  (a reta daria 23.5: nota maior que 10!)
import numpy as np


def reta_minimos_quadrados(x, y):
    """JÁ ESCRITA."""
    x = np.array(x)
    y = np.array(y)
    n = len(x)
    A = np.array([[n, np.sum(x)], [np.sum(x), np.sum(x**2)]])
    b = np.array([np.sum(y), np.sum(x * y)])
    a = np.linalg.solve(A, b)
    return (a[0], a[1])


def previsao_nota(horas):
    """Nota prevista pela reta; None fora da faixa das horas observadas."""
    horas_estudo = [2, 4, 5, 6, 8, 9, 10, 12]
    notas = [4.1, 5.0, 5.6, 6.3, 7.0, 7.9, 8.2, 9.1]
    # TODO: se horas estiver fora da faixa, return None; senão, a reta
    pass


# --- testes (não altere) ---
assert abs(previsao_nota(7) - 6.65) < 1e-9
assert previsao_nota(40) is None, "fora da faixa: não extrapole"
assert previsao_nota(1) is None
print("Exercício 06: todos os testes passaram!")