W3docs

Regressão Múltipla

Aprenda como funciona a regressão linear múltipla, interprete coeficientes, trate multicolinearidade e construa um modelo completo em Python com scikit-learn.

A regressão linear múltipla estende a regressão linear simples para usar duas ou mais variáveis independentes na previsão de um alvo contínuo. Em vez de traçar uma linha em duas dimensões, o modelo ajusta um hiperplano através de tantas dimensões quantas forem as características. Compreender como os coeficientes interagem — e quando eles podem enganar — é a habilidade central que esta página ensina.

Esta página aborda:

  • A equação de regressão múltipla e o que cada coeficiente significa
  • Como construir um pipeline completo com scikit-learn: carregar, pré-processar, treinar, avaliar
  • Por que o escalonamento de características é importante e como fazê-lo corretamente
  • Como interpretar e comparar coeficientes escalonados e não escalonados
  • Diagnosticar multicolinearidade — o problema mais comum na regressão múltipla
  • Análise de resíduos para verificar as suposições do modelo
  • Quando escolher a regressão múltipla e o que tentar quando ela não é suficiente

A Equação da Regressão Múltipla

A regressão linear múltipla modela o alvo y como uma combinação linear de n características de entrada:

y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + ε
  • β₀ — o intercepto: o valor previsto de y quando todas as características são iguais a zero
  • β₁ … βₙ — os coeficientes: quanto y muda para um aumento de uma unidade em cada xᵢ, mantendo todas as outras características constantes
  • ε — o termo de erro: a parte de y que o modelo não consegue explicar

O algoritmo encontra os coeficientes minimizando a soma dos quadrados dos resíduos (mínimos quadrados ordinários):

SSR = Σ(yᵢ - ŷᵢ)²

Isso tem uma solução analítica exata em forma fechada, portanto o LinearRegression do scikit-learn não precisa de descida de gradiente iterativa — o treinamento é quase instantâneo mesmo em conjuntos de dados com centenas de milhares de linhas.

Diferença em Relação à Regressão Linear Simples

A regressão linear simples usa uma característica. A regressão múltipla adiciona mais características para que cada coeficiente capture o efeito parcial dessa característica — seu impacto no alvo enquanto as demais características permanecem constantes. Isso é mais poderoso, mas introduz novos riscos, especialmente a multicolinearidade (veja Diagnosticando a Multicolinearidade).

O Conjunto de Dados

Os exemplos abaixo utilizam o conjunto de dados California Housing integrado ao scikit-learn. Ele registra estatísticas habitacionais em nível de bloco censitário para a Califórnia em 1990 e possui 20.640 amostras com 8 características.

import pandas as pd
from sklearn.datasets import fetch_california_housing

housing = fetch_california_housing()
df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['MedHouseVal'] = housing.target  # median house value in $100,000s

print(df.shape)      # (20640, 9)
print(df.head())

As 8 características de entrada são:

CaracterísticaDescrição
MedIncRenda mediana no bloco (em dezenas de milhares de dólares)
HouseAgeIdade mediana das casas no bloco
AveRoomsNúmero médio de cômodos por domicílio
AveBedrmsNúmero médio de quartos por domicílio
PopulationPopulação do bloco
AveOccupOcupação média por domicílio
LatitudeLatitude do bloco
LongitudeLongitude do bloco

O alvo MedHouseVal é o valor mediano das casas em unidades de $100.000, portanto um valor de 2.0 representa $200.000.

Construindo o Modelo Passo a Passo

Passo 1 — Dividir os Dados

Sempre divida os dados antes de qualquer pré-processamento. Ajustar um escalonador no conjunto de dados completo vazaria as estatísticas do conjunto de teste para o treinamento, fornecendo uma avaliação excessivamente otimista. Veja Divisão Treino/Teste para uma explicação completa.

from sklearn.model_selection import train_test_split

X = df[housing.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
)

print(f"Training samples: {len(X_train)}")  # 16512
print(f"Test samples:     {len(X_test)}")   # 4128

Passo 2 — Escalonar as Características

Os coeficientes da regressão múltipla refletem as unidades de cada característica. MedInc é medida em dezenas de milhares de dólares; Population é uma contagem bruta que pode chegar a 35.000. Sem escalonamento, o coeficiente de Population será pequeno não porque a população seja irrelevante, mas porque sua unidade é pequena.

O StandardScaler transforma cada característica para ter média zero e desvio padrão unitário, tornando as magnitudes dos coeficientes diretamente comparáveis. Veja Escalonamento de Características para detalhes sobre os escalonadores disponíveis.

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)   # fit ONLY on training data
X_test_scaled  = scaler.transform(X_test)         # apply the same transformation

A regra crítica: chame fit_transform nos dados de treinamento e transform (sem ajuste) nos dados de teste. Ajustar nos dados de teste contaminaria a avaliação.

Passo 3 — Treinar o Modelo

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X_train_scaled, y_train)

LinearRegression.fit() resolve o problema de MQO analiticamente. Não há hiperparâmetros a ajustar na regressão múltipla simples — o que você escolhe é quais características incluir.

Passo 4 — Avaliar o Modelo

import numpy as np
from sklearn.metrics import mean_squared_error, r2_score

y_pred = model.predict(X_test_scaled)

mse  = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
r2   = r2_score(y_test, y_pred)

print(f"Mean Squared Error:      {mse:.4f}")
print(f"Root Mean Squared Error: {rmse:.4f}  (±${rmse * 100_000:,.0f})")
print(f"R-squared:               {r2:.4f}")

Saída esperada:

Mean Squared Error:      0.5559
Root Mean Squared Error: 0.7456  (±$74,558)
R-squared:               0.5758

O que as métricas significam:

  • MSE (Erro Quadrático Médio) — média das diferenças ao quadrado entre previsões e valores reais. O quadrado penaliza erros grandes mais do que erros pequenos. As unidades são o quadrado do alvo ($100.000²), portanto é mais difícil de interpretar diretamente.
  • RMSE (Raiz do Erro Quadrático Médio) — a raiz quadrada do MSE, de volta nas mesmas unidades do alvo. Um RMSE de 0,75 significa que as previsões do modelo diferem em cerca de $75.000 em média.
  • R² (coeficiente de determinação) — a fração da variância no alvo que o modelo explica. Um R² de 0,58 significa que o modelo captura 58% da variação nos preços das casas. Os valores variam de 0 (não melhor do que prever a média) a 1 (previsões perfeitas). R² negativo é possível se o modelo for pior do que a média — isso é um forte sinal de que algo está errado.

Um R² de ~0,58 é típico para este conjunto de dados com regressão linear simples. A relação entre preços de casas e essas características é parcialmente não linear e envolve agrupamento geográfico que um hiperplano não consegue capturar bem. Algoritmos como árvores com gradiente boosting atingem rotineiramente 0,80+ neste conjunto de dados.

Passo 5 — Inspecionar os Coeficientes

Após o escalonamento, as magnitudes dos coeficientes são diretamente comparáveis — elas mostram quais características influenciam mais fortemente a previsão:

coef_df = pd.DataFrame({
    'Feature':     housing.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 esperada:

   Feature  Coefficient
  Latitude    -0.8969
 Longitude    -0.8698
    MedInc     0.8544
 AveBedrms     0.3393
  AveRooms    -0.2944
  HouseAge     0.1225
  AveOccup    -0.0408
Population    -0.0023

Intercept: 2.0719

Lendo os coeficientes após o escalonamento padrão:

  • MedInc = 0.854 — o preditor mais forte isolado. Um aumento de um desvio padrão na renda mediana prevê um aumento de $85.400 no valor da casa, mantendo tudo o mais constante.
  • Latitude = -0.897 e Longitude = -0.869 — o modelo aprendeu que blocos censitários mais ao norte e mais a leste tendem a ser mais baratos. No entanto, essas duas características geográficas são altamente correlacionadas (r = -0,93), o que pode tornar seus coeficientes individuais instáveis (veja Diagnosticando a Multicolinearidade).
  • AveBedrms = +0.339 vs AveRooms = -0.294 — estes têm sinais opostos, mesmo que mais cômodos e mais quartos geralmente signifiquem casas maiores e mais caras. Este é um sinal clássico de multicolinearidade: AveRooms e AveBedrms são correlacionadas (r = 0,85), portanto seus coeficientes se compensam mutuamente. Não os interprete isoladamente.
  • Population = -0.002 — muito próximo de zero após o escalonamento. A população do bloco tem poder preditivo mínimo quando as outras características são levadas em conta.

O intercepto (2,07) é o MedHouseVal previsto quando todas as características escalonadas são zero — ou seja, quando todas as características estão na sua média do conjunto de treinamento. Ele é igual à média dos alvos de treinamento e não tem significado de negócio direto além disso.

Passo 6 — Fazer Previsões em Novos Dados

# A new census block: high income, older house, San Francisco Bay Area
new_block = pd.DataFrame([[8.0, 41.0, 6.0, 1.0, 322, 2.5, 37.88, -122.23]],
                         columns=housing.feature_names)

new_block_scaled = scaler.transform(new_block)
prediction = model.predict(new_block_scaled)

print(f"Predicted median house value: ${prediction[0] * 100_000:,.0f}")

Saída esperada:

Predicted median house value: $410,895

O escalonador deve ser o mesmo escalonador ajustado nos dados de treinamento. Nunca reajuste o escalonador nos novos dados — isso deslocaria as entradas em relação ao que o modelo aprendeu.

Diagnosticando a Multicolinearidade

A multicolinearidade ocorre quando duas ou mais variáveis independentes são altamente correlacionadas entre si. Isso não impede o modelo de fazer previsões precisas, mas torna os coeficientes individuais não confiáveis e difíceis de interpretar. Os coeficientes podem se tornar grandes, mudar de sinal ou tornar-se estatisticamente insignificantes mesmo para características genuinamente importantes.

Verificando com uma Matriz de Correlação

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

corr = df[housing.feature_names].corr()
print(corr.round(2))

Pares principais a observar:

Par de característicasCorrelaçãoPreocupação
AveRooms / AveBedrms0,85Alta — coeficientes se compensam mutuamente
Latitude / Longitude-0,93Muito alta — covariação geográfica
MedInc / MedHouseVal (alvo)0,69Bom preditor, não é um problema de colinearidade

Uma correlação acima de 0,80 entre duas características é um sinal de alerta. Ao identificá-la, considere:

  1. Remover uma das características correlacionadas. Se AveRooms e AveBedrms estão ambas no modelo, tente remover AveBedrms e verifique se o desempenho preditivo do modelo muda muito.
  2. Combiná-las. Crie uma característica derivada (por exemplo, rooms_per_bedroom = AveRooms / AveBedrms) que capture a relação sem redundância.
  3. Usar um modelo regularizado. A regressão Ridge adiciona uma penalidade L2 que encolhe os coeficientes correlacionados entre si, estabilizando-os. O Lasso (L1) pode zerar características redundantes completamente.

Análise de Resíduos

Um resíduo é a diferença entre um valor real e a previsão do modelo: residual = y_actual - y_predicted. Plotar os resíduos revela se as suposições do modelo são válidas.

residuals = y_test - y_pred

print(f"Mean of residuals: {residuals.mean():.4f}")  # should be close to 0
print(f"Std of residuals:  {residuals.std():.4f}")

Saída esperada:

Mean of residuals: 0.0035
Std of residuals:  0.7457

A média está próxima de zero — um sinal de que o modelo é imparcial em média. Mas o desvio padrão de 0,75 (±$75.000) mostra dispersão substancial.

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt

fig, axes = plt.subplots(1, 2, figsize=(12, 4))

# Predicted vs Actual
axes[0].scatter(y_test, y_pred, alpha=0.2, s=8)
axes[0].plot([0, 5], [0, 5], 'r--')
axes[0].set_xlabel('Actual')
axes[0].set_ylabel('Predicted')
axes[0].set_title('Predicted vs Actual')

# Residuals vs Predicted
axes[1].scatter(y_pred, residuals, alpha=0.2, s=8)
axes[1].axhline(0, color='r', linestyle='--')
axes[1].set_xlabel('Predicted')
axes[1].set_ylabel('Residual')
axes[1].set_title('Residuals vs Predicted')

plt.tight_layout()
plt.savefig('residuals.png', dpi=120)
print("Saved residuals.png")

O que observar:

  • Previsto vs Real — idealmente, os pontos se distribuem ao longo da diagonal. Desvio sistemático da diagonal (uma curva ou um achatamento em valores altos) indica que a suposição linear está errada para parte do intervalo.
  • Resíduos vs Previsto — idealmente, os resíduos se dispersam aleatoriamente em torno de zero em todos os níveis de previsão. Uma forma de funil (maior dispersão em previsões mais altas) sinaliza heterocedasticidade — o erro do modelo não é constante, o que pode tornar as estimativas de intervalo não confiáveis.
  • Agrupamentos — grupos distintos no gráfico de resíduos podem revelar que o conjunto de dados contém subpopulações (por exemplo, urbano vs rural) que justificam modelos separados ou características adicionais.

Pipeline Completo

Aqui está tudo o que foi apresentado acima como um script executável único:

import numpy as np
import pandas as pd
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, r2_score

# 1. Load data
housing = fetch_california_housing()
df = pd.DataFrame(housing.data, columns=housing.feature_names)
df['MedHouseVal'] = housing.target

# 2. Split — before any preprocessing
X = df[housing.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
)

# 3. Scale
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled  = scaler.transform(X_test)

# 4. Train
model = LinearRegression()
model.fit(X_train_scaled, y_train)

# 5. Evaluate
y_pred = model.predict(X_test_scaled)
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}")

# 6. Coefficients (most important first)
coef_df = pd.DataFrame({
    'Feature':     housing.feature_names,
    'Coefficient': model.coef_
}).sort_values('Coefficient', key=abs, ascending=False)
print(coef_df.to_string(index=False))

Quando Usar a Regressão Múltipla

A regressão múltipla é uma boa primeira escolha quando:

  • A relação entre cada característica e o alvo é aproximadamente linear
  • A interpretabilidade importa — cada coeficiente tem um significado claro
  • Você quer uma linha de base rápida antes de tentar modelos complexos
  • Você tem amostras suficientes em relação ao número de características (uma regra geral: pelo menos 10–20 observações por característica)

Considere alternativas quando:

SituaçãoAlternativa
Relações não lineares entre característica e alvoRegressão Polinomial
Muitas características, risco de sobreajusteRidge ou Lasso (modelos lineares regularizados)
O alvo é uma categoria, não um númeroRegressão Logística
Interações complexas e não linearidadeÁrvores com gradiente boosting ou florestas aleatórias

Armadilhas Comuns

Ajustar o escalonador em todos os dados antes de dividir. Isso vaza a média e a variância do conjunto de teste para o treinamento. Sempre divida primeiro, depois ajuste o escalonador apenas na parte de treinamento.

Adicionar mais características sempre ajuda. Adicionar características irrelevantes ou redundantes pode reduzir a interpretabilidade, introduzir multicolinearidade e prejudicar a generalização. Use conhecimento de domínio ou uma técnica de seleção de características para escolher as características de forma deliberada.

Confiar nos coeficientes quando as características são correlacionadas. Quando AveRooms e AveBedrms estão ambas no modelo, nenhum dos coeficientes reflete de forma confiável o efeito real dessa variável. Verifique a matriz de correlação antes de interpretar coeficientes individuais.

Ignorar os gráficos de resíduos. Um R² de 0,58 parece razoável no papel, mas padrões nos resíduos podem revelar que o modelo está sistematicamente errado para propriedades de alto valor ou para regiões geográficas específicas.

Extrapolar além do intervalo de treinamento. Um modelo linear treinado em casas com preços entre $50.000 e $500.000 não deve ser usado para prever propriedades de $5.000.000. Verifique se as novas entradas estão dentro do intervalo visto durante o treinamento.

Próximos Passos

Was this page helpful?