Regressão Linear
Aprenda como a regressão linear funciona, entenda a matemática por trás dela e implemente regressão linear simples e múltipla em Python usando scikit-learn.
A regressão linear é um dos algoritmos mais fundamentais em machine learning. Ela modela a relação entre uma variável dependente (o que você quer prever) e uma ou mais variáveis independentes (as entradas), ajustando uma linha reta — ou um hiperplano — aos dados.
Esta página aborda:
- Como a regressão linear simples e múltipla funcionam matematicamente
- O método dos mínimos quadrados ordinários (OLS) para ajustar uma linha
- Principais premissas que você deve verificar antes de confiar no seu modelo
- Um guia completo com scikit-learn: carregar dados, treinar, avaliar e interpretar resultados
- Como ler os coeficientes do modelo e identificar armadilhas comuns
Como a Regressão Linear Funciona
A Equação
A regressão linear simples (uma variável de entrada) ajusta esta linha:
y = β₀ + β₁x + εy— a variável dependente (alvo)x— a variável independente (feature)β₀— o intercepto (valor de y quando x = 0)β₁— a inclinação (variação de y para um aumento de uma unidade em x)ε— o termo de erro (ruído que o modelo não consegue explicar)
A regressão linear múltipla estende isso para n features:
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + εCada coeficiente βᵢ indica o quanto y muda quando xᵢ aumenta em uma unidade, mantendo todas as outras features constantes.
Mínimos Quadrados Ordinários (OLS)
O modelo aprende os coeficientes minimizando a soma dos resíduos ao quadrado — a diferença entre cada valor real yᵢ e a previsão do modelo ŷᵢ:
SSR = Σ(yᵢ - ŷᵢ)²Elevar os resíduos ao quadrado penaliza erros grandes mais do que erros pequenos e garante que erros positivos e negativos não se anulem. Este critério tem uma solução analítica exata, razão pela qual a regressão linear treina quase instantaneamente mesmo em grandes conjuntos de dados.
Premissas Fundamentais
A regressão linear produz previsões confiáveis somente quando estas condições são atendidas:
| Premissa | O que verificar |
|---|---|
| Linearidade | A relação entre as features e o alvo é aproximadamente linear |
| Independência | As observações são independentes entre si |
| Homocedasticidade | A variância dos resíduos é aproximadamente constante em todas as previsões |
| Normalidade dos resíduos | Os resíduos são aproximadamente distribuídos normalmente |
| Ausência de multicolinearidade | As variáveis independentes não são altamente correlacionadas entre si |
Quando essas premissas são violadas, as estimativas dos coeficientes podem ser tendenciosas ou o modelo pode ter desempenho ruim em dados não vistos.
Exemplo de Regressão Linear Simples
Antes de passar para múltiplas features, vamos ver como o algoritmo ajusta uma linha a uma única feature. Isso torna a geometria fácil de visualizar.
import numpy as np
import matplotlib
matplotlib.use('Agg') # non-interactive backend for scripts
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# Simulate: house size (sq ft) vs price ($1000s)
rng = np.random.default_rng(42)
X_simple = rng.uniform(500, 3000, 50).reshape(-1, 1)
y_simple = 50 + 0.1 * X_simple.ravel() + rng.normal(0, 15, 50)
model = LinearRegression()
model.fit(X_simple, y_simple)
print(f"Intercept (β₀): {model.intercept_:.2f}")
print(f"Slope (β₁): {model.coef_[0]:.4f}")
print(f"Interpretation: each extra sq ft adds ${model.coef_[0]*1000:.0f} to the predicted price")Saída esperada:
Intercept (β₀): 46.17
Slope (β₁): 0.1007
Interpretation: each extra sq ft adds $101 to the predicted priceO intercepto e a inclinação são recuperados automaticamente pelo OLS — você não precisa fazer nenhuma álgebra por conta própria.
Regressão Linear Múltipla com scikit-learn
Conjuntos de dados reais têm muitas features. Esta seção percorre um pipeline completo no conjunto de dados California Housing, que registra estatísticas habitacionais no nível de bloco censitário para a Califórnia em 1990.
Passo 1: Importar Bibliotecas
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_scorePasso 2: Carregar e Explorar o Conjunto de Dados
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target # median house value in $100,000s
print(df.shape) # (20640, 9)
print(df.head())
print(df.describe())O conjunto de dados tem 20.640 linhas e 8 features de entrada:
| Feature | Descrição |
|---|---|
MedInc | Renda mediana no bloco (em dezenas de milhares de dólares) |
HouseAge | Idade mediana das casas no bloco |
AveRooms | Número médio de quartos por domicílio |
AveBedrms | Número médio de dormitórios por domicílio |
Population | População do bloco |
AveOccup | Ocupação média por domicílio |
Latitude | Latitude do bloco |
Longitude | Longitude do bloco |
O alvo MedHouseVal é o valor mediano das casas em unidades de $100.000.
Passo 3: Escolher Features e Dividir os Dados
Para uma demonstração direta, usamos todas as 8 features. Consulte Train/Test Split para uma explicação detalhada de por que dividimos os dados.
X = df[california.feature_names] # all 8 features
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42
)
print(f"Training samples: {len(X_train)}") # 16512
print(f"Test samples: {len(X_test)}") # 4128O random_state=42 garante divisões reproduzíveis toda vez que você executa o script.
Passo 4: Treinar o Modelo
model = LinearRegression()
model.fit(X_train, y_train)É só isso. O método fit() resolve o problema OLS analiticamente usando álgebra matricial — por padrão, não há gradiente descendente iterativo envolvido.
Passo 5: Inspecionar os Coeficientes Aprendidos
Entender o que o modelo aprendeu é tão importante quanto sua precisão:
coef_df = pd.DataFrame({
'Feature': california.feature_names,
'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)
print(coef_df.to_string(index=False))
print(f"\nIntercept: {model.intercept_:.4f}")Saída típica:
Feature Coefficient
AveBedrms 0.7831
MedInc 0.4487
Longitude -0.4337
Latitude -0.4198
AveRooms -0.1233
HouseAge 0.0097
AveOccup -0.0035
Population -0.0000
Intercept: -37.0233Lendo os coeficientes:
AveBedrms = 0.783: um aumento de uma unidade no número médio de dormitórios prevê um aumento de $78.300 no valor da casa — mas isso está entrelaçado comAveRooms(eles são correlacionados). Quando features correlacionadas estão ambas presentes, os coeficientes individuais podem se tornar grandes, instáveis ou até contraintuitivos. Isso é multicolinearidade.MedInc = 0.449: um aumento de uma unidade na renda mediana (aproximadamente $10.000) prevê um aumento de $44.900 no valor da casa, mantendo todo o resto constante.Longitude = -0.434eLatitude = -0.420: controles puramente geográficos; o modelo os usa para capturar efeitos de localização, embora não consiga modelar bem a geografia não linear.
Passo 6: Avaliar o Modelo
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.4f} (in $100,000s, so ±${rmse*100_000:,.0f})")
print(f"R²: {r2:.4f}")Saída esperada:
RMSE: 0.7456 (in $100,000s, so ±$74,560)
R²: 0.5758Interpretando as métricas:
- RMSE (Erro Quadrático Médio Raiz) — o erro médio de previsão nas mesmas unidades do alvo. Menor é melhor.
- R² (coeficiente de determinação) — a proporção da variância em
yque o modelo explica. Um R² de 0,58 significa que o modelo explica cerca de 58% da variância nos preços das casas. Valores mais próximos de 1,0 são melhores; valores próximos de 0 significam que o modelo é apenas um pouco melhor do que prever a média.
Um R² de ~0,58 é típico para este conjunto de dados com regressão linear. A relação entre os preços das casas e essas features é parcialmente não linear, razão pela qual métodos como regressão polinomial ou gradient boosting frequentemente obtêm pontuações mais altas.
Passo 7: Visualizar Valores Previstos vs. Reais
O gráfico diagnóstico mais claro para um modelo de regressão é previsto vs. real — ele funciona independentemente de quantas features você tem:
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.figure(figsize=(7, 5))
plt.scatter(y_test, y_pred, alpha=0.3, s=10, color='steelblue')
plt.plot([y_test.min(), y_test.max()],
[y_test.min(), y_test.max()],
'r--', linewidth=1.5, label='Perfect prediction')
plt.xlabel('Actual Median House Value ($100,000s)')
plt.ylabel('Predicted Median House Value ($100,000s)')
plt.title('Linear Regression: Predicted vs Actual')
plt.legend()
plt.tight_layout()
plt.savefig('lr_predicted_vs_actual.png', dpi=120)
print("Plot saved.")Pontos que caem na linha tracejada vermelha são previsões perfeitas. A dispersão ao redor da linha mostra o erro. Uma forma de leque (dispersão maior em valores mais altos) sinaliza heterocedasticidade — uma das premissas fundamentais é violada.
Pipeline Completo (Todos os Passos Juntos)
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
# Load data
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target
# Split
X = df[california.feature_names]
y = df['MedHouseVal']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Train
model = LinearRegression()
model.fit(X_train, y_train)
# Evaluate
y_pred = model.predict(X_test)
rmse = np.sqrt(mean_squared_error(y_test, y_pred))
r2 = r2_score(y_test, y_pred)
print(f"RMSE: {rmse:.4f}")
print(f"R²: {r2:.4f}")Quando Usar a Regressão Linear
A regressão linear é uma boa primeira escolha quando:
- A relação entre entradas e saída é aproximadamente linear
- A interpretabilidade importa — você precisa explicar previsões para as partes interessadas
- O conjunto de dados é pequeno ou médio e a velocidade de treinamento é importante
- Você quer uma baseline rápida antes de tentar modelos mais complexos
Considere alternativas quando:
- As features e o alvo têm relações fortemente não lineares → experimente regressão polinomial ou árvores de decisão
- Você tem muitas features que podem ser irrelevantes → variantes regularizadas (Ridge, Lasso) evitam overfitting ao reduzir os coeficientes
- O alvo é uma categoria, não um número → use regressão logística
Armadilhas Comuns
Esquecer de escalar as features. Os coeficientes da regressão linear refletem as unidades de cada feature. Se uma feature está em milhares e outra em frações, os tamanhos brutos dos coeficientes não são comparáveis. Use StandardScaler antes de comparar a importância das features. Consulte Feature Scaling para mais detalhes.
Multicolinearidade. Features altamente correlacionadas tornam os coeficientes individuais não confiáveis — eles podem até trocar de sinal. Verifique a matriz de correlação com df.corr() e remova ou combine features correlacionadas.
Extrapolação. Um modelo linear treinado em dados em um determinado intervalo pode dar previsões completamente erradas fora desse intervalo. Sempre verifique se as novas entradas estão dentro da distribuição de treinamento.
Ignorar gráficos de resíduos. Sempre trace os resíduos após o ajuste. Padrões nos resíduos (curvas, leques, clusters de outliers) indicam que as premissas do modelo foram violadas e as previsões não devem ser confiadas sem investigação adicional.
Próximos Passos
Depois de ter uma baseline de regressão linear funcionando, explore estes tópicos relacionados:
- Multiple Regression — análise mais aprofundada sobre o uso de múltiplas features e a interpretação de cada coeficiente
- Polynomial Regression — ajuste curvas em vez de linhas adicionando termos de feature polinomial
- Train/Test Split — entenda por que e como avaliar corretamente o desempenho do modelo
- Feature Scaling — padronize as entradas para que os coeficientes e os solvers baseados em gradiente se comportem corretamente
- Logistic Regression — preveja categorias (sim/não, spam/não-spam) em vez de valores contínuos