Skip to content

Regressão Linear no Sklearn: Guia Completo com Exemplos em Python

Updated on

Você tem um dataset com features e uma variável-alvo contínua. Você quer prever resultados — preços de imóveis, receita de vendas, tendências de temperatura — mas não tem certeza de qual abordagem usar ou como configurar tudo corretamente em Python. A escolha errada do modelo ou a falta de etapas de pré-processamento levam a previsões ruins e a tempo perdido depurando.

A regressão linear é o algoritmo mais usado para tarefas de previsão contínua, mas fazê-la corretamente envolve mais do que chamar .fit() e .predict(). Você precisa entender como o modelo funciona internamente, quando ele falha, como avaliá-lo corretamente e quando mudar para variantes regularizadas como Ridge ou Lasso. Pular essas etapas significa colocar em produção modelos que vão bem nos dados de treino, mas desmoronam em novas observações.

O Scikit-learn oferece LinearRegression juntamente com um ecossistema completo de ferramentas para pré-processamento, avaliação e regularização. Este guia cobre tudo, do uso básico até pipelines de regressão prontos para produção.

📚

O que é Regressão Linear?

A regressão linear modela a relação entre uma ou mais features de entrada e uma saída contínua ajustando uma linha reta (ou hiperplano) que minimiza a soma dos resíduos ao quadrado. A equação para um modelo com n features é:

y = b0 + b1*x1 + b2*x2 + ... + bn*xn

Onde b0 é o intercepto (termo de viés), b1...bn são os coeficientes (pesos) de cada feature, e y é o valor previsto.

O modelo encontra os coeficientes que minimizam a função de custo de Ordinary Least Squares (OLS):

Cost = Sum of (y_actual - y_predicted)^2

Isso tem uma solução de forma fechada, então o treino é rápido mesmo em datasets grandes.

Regressão Linear Simples com Sklearn

A regressão linear simples usa uma única feature para prever o alvo. Aqui está um exemplo completo:

from sklearn.linear_model import LinearRegression
import numpy as np
 
# Sample data: years of experience vs salary (in thousands)
X = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).reshape(-1, 1)
y = np.array([35, 40, 45, 55, 60, 62, 70, 75, 82, 90])
 
# Create and train the model
model = LinearRegression()
model.fit(X, y)
 
# Model parameters
print(f"Coefficient (slope): {model.coef_[0]:.4f}")
print(f"Intercept: {model.intercept_:.4f}")
 
# Predict salary for 12 years of experience
prediction = model.predict([[12]])
print(f"Predicted salary for 12 years: ${prediction[0]:.2f}k")
# Coefficient (slope): 5.9394
# Intercept: 28.3333
# Predicted salary for 12 years: $99.61k

Entendendo a Saída

AttributeMeaningExample Value
model.coef_Peso para cada feature[5.94] -- o salário aumenta ~$5,940 por ano
model.intercept_y previsto quando todas as features são 028.33 -- salário base de $28,330
model.score(X, y)R-squared nos dados fornecidos0.98

Regressão Linear Múltipla

Quando você tem mais de uma feature, o modelo ajusta um hiperplano em vez de uma linha:

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
import numpy as np
 
# Load California housing dataset
housing = fetch_california_housing()
X, y = housing.data, housing.target
feature_names = housing.feature_names
 
print(f"Features: {feature_names}")
print(f"Dataset shape: {X.shape}")  # (20640, 8)
 
# Split into train and test
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
 
# Train model
model = LinearRegression()
model.fit(X_train, y_train)
 
# Print coefficients for each feature
print("\nFeature Coefficients:")
for name, coef in zip(feature_names, model.coef_):
    print(f"  {name:12s}: {coef:+.6f}")
print(f"  {'Intercept':12s}: {model.intercept_:+.6f}")
 
# Evaluate
train_score = model.score(X_train, y_train)
test_score = model.score(X_test, y_test)
print(f"\nR² (train): {train_score:.4f}")
print(f"R² (test):  {test_score:.4f}")

Avaliação do Modelo: R-squared, MSE e RMSE

R-squared sozinho não conta a história toda. Use múltiplas métricas para avaliar modelos de regressão:

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from sklearn.datasets import fetch_california_housing
import numpy as np
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
 
# Calculate metrics
r2 = r2_score(y_test, y_pred)
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred)
 
print(f"R² Score:  {r2:.4f}")
print(f"MSE:       {mse:.4f}")
print(f"RMSE:      {rmse:.4f}")
print(f"MAE:       {mae:.4f}")
# R² Score:  0.5758
# MSE:       0.5559
# RMSE:      0.7456
# MAE:       0.5332

Métricas de Avaliação Explicadas

MetricFormulaRangeInterpretation
R-squared (R²)1 - (SS_res / SS_tot)(-inf, 1]Proporção da variância explicada. 1.0 = perfeito, 0 = não melhor que a média
MSEmean((y - y_pred)²)[0, inf)Erro quadrático médio. Penaliza mais erros grandes
RMSEsqrt(MSE)[0, inf)Mesmas unidades da variável-alvo. Mais fácil de interpretar que o MSE
MAEmean(|y - y_pred|)[0, inf)Erro absoluto médio. Mais robusto a outliers

Um R-squared baixo nem sempre significa um modelo ruim. Para dados ruidosos do mundo real (como preços de imóveis), R² = 0.6 pode ser razoável. Sempre compare o RMSE com a escala da sua variável-alvo.

Feature Scaling para Regressão Linear

O LinearRegression padrão não exige escalonamento de features porque usa OLS com solução de forma fechada. No entanto, o escalonamento se torna essencial ao usar regularização:

from sklearn.linear_model import LinearRegression, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_california_housing
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
# Without scaling (fine for basic LinearRegression)
model_no_scale = LinearRegression()
model_no_scale.fit(X_train, y_train)
print(f"LinearRegression R² (no scaling): {model_no_scale.score(X_test, y_test):.4f}")
 
# With scaling via Pipeline (required for regularized models)
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('ridge', Ridge(alpha=1.0))
])
pipeline.fit(X_train, y_train)
print(f"Ridge R² (with scaling):          {pipeline.score(X_test, y_test):.4f}")

Por que o escalonamento importa para regularização: Ridge e Lasso penalizam coeficientes grandes de forma “igual”. Se uma feature varia de 0 a 1 e outra de 0 a 100.000, a penalização encolhe de maneira desproporcional o coeficiente da feature de menor escala. O escalonamento coloca todas as features na mesma escala para que a penalidade seja aplicada de forma justa.

Features Polinomiais: Modelando Relações Não Lineares

Quando a relação entre as features e o alvo não é linear, features polinomiais podem capturar curvas e interações:

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score
import numpy as np
 
# Generate non-linear data
np.random.seed(42)
X = np.linspace(0, 10, 200).reshape(-1, 1)
y = 3 * X.ravel()**2 - 5 * X.ravel() + 10 + np.random.randn(200) * 15
 
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)
 
# Linear model
linear = LinearRegression()
linear.fit(X_train, y_train)
print(f"Linear R²: {r2_score(y_test, linear.predict(X_test)):.4f}")
 
# Polynomial (degree 2) model
poly_pipeline = Pipeline([
    ('poly', PolynomialFeatures(degree=2, include_bias=False)),
    ('linear', LinearRegression())
])
poly_pipeline.fit(X_train, y_train)
print(f"Poly (d=2) R²: {r2_score(y_test, poly_pipeline.predict(X_test)):.4f}")
 
# Polynomial (degree 3) model
poly3_pipeline = Pipeline([
    ('poly', PolynomialFeatures(degree=3, include_bias=False)),
    ('linear', LinearRegression())
])
poly3_pipeline.fit(X_train, y_train)
print(f"Poly (d=3) R²: {r2_score(y_test, poly3_pipeline.predict(X_test)):.4f}")

Aviso: polinômios de alto grau sofrem overfitting rapidamente. Use validação cruzada para selecionar o grau certo e prefira regularização em modelos polinomiais.

Regularização: Ridge, Lasso e ElasticNet

Quando seu modelo tem muitas features ou termos polinomiais, a regularização evita overfitting adicionando uma penalidade para coeficientes grandes.

Ridge Regression (Penalidade L2)

Ridge adiciona a soma dos coeficientes ao quadrado à função de custo. Ele reduz (shrink) os coeficientes em direção a zero, mas nunca os zera exatamente.

from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
import numpy as np
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
# Find best alpha with cross-validation
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('ridge', Ridge())
])
 
param_grid = {'ridge__alpha': [0.01, 0.1, 1.0, 10.0, 100.0]}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
 
print(f"Best alpha: {grid.best_params_['ridge__alpha']}")
print(f"Best CV R²: {grid.best_score_:.4f}")
print(f"Test R²:    {grid.score(X_test, y_test):.4f}")

Lasso Regression (Penalidade L1)

Lasso adiciona a soma dos valores absolutos dos coeficientes. Ele pode zerar coeficientes exatamente, fazendo seleção automática de features:

from sklearn.linear_model import Lasso
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
import numpy as np
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('lasso', Lasso(max_iter=10000))
])
 
param_grid = {'lasso__alpha': [0.001, 0.01, 0.1, 1.0, 10.0]}
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
 
print(f"Best alpha: {grid.best_params_['lasso__alpha']}")
print(f"Test R²:    {grid.score(X_test, y_test):.4f}")
 
# Show which features were selected (non-zero coefficients)
lasso_model = grid.best_estimator_.named_steps['lasso']
feature_names = housing.feature_names
for name, coef in zip(feature_names, lasso_model.coef_):
    status = "KEPT" if abs(coef) > 1e-6 else "DROPPED"
    print(f"  {name:12s}: {coef:+.6f}  [{status}]")

ElasticNet (Penalidade L1 + L2)

ElasticNet combina as penalidades Ridge e Lasso. O parâmetro l1_ratio controla a mistura: 0 = Ridge puro, 1 = Lasso puro.

from sklearn.linear_model import ElasticNet
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.datasets import fetch_california_housing
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
pipeline = Pipeline([
    ('scaler', StandardScaler()),
    ('elasticnet', ElasticNet(max_iter=10000))
])
 
param_grid = {
    'elasticnet__alpha': [0.01, 0.1, 1.0],
    'elasticnet__l1_ratio': [0.1, 0.3, 0.5, 0.7, 0.9]
}
 
grid = GridSearchCV(pipeline, param_grid, cv=5, scoring='r2')
grid.fit(X_train, y_train)
 
print(f"Best alpha:    {grid.best_params_['elasticnet__alpha']}")
print(f"Best l1_ratio: {grid.best_params_['elasticnet__l1_ratio']}")
print(f"Test R²:       {grid.score(X_test, y_test):.4f}")

Comparação: LinearRegression vs Ridge vs Lasso vs ElasticNet

ModelPenaltyFeature SelectionWhen to UseScaling Required
LinearRegressionNenhumaNãoPoucas features, sem multicolinearidade, boa relação sinal-ruídoNão
RidgeL2 (quadrática)Não (encolhe em direção a zero)Muitas features correlacionadas, quer manter todas as featuresSim
LassoL1 (absoluta)Sim (zera coeficientes)Muitas features, quer seleção automática de featuresSim
ElasticNetL1 + L2Sim (parcial)Muitas features correlacionadas, quer alguma seleção de featuresSim

Escolhendo o Modelo Certo

Use LinearRegression como baseline. Se o modelo fizer overfit (grande diferença entre R-squared de treino e teste), tente Ridge primeiro. Se você suspeitar que há muitas features irrelevantes, tente Lasso. Se as features forem correlacionadas e você quiser seleção, tente ElasticNet. Sempre use validação cruzada para comparar.

Suposições da Regressão Linear

A regressão linear produz resultados confiáveis quando estas suposições se mantêm:

  1. Linearidade — A relação entre features e alvo é linear (ou pode ser linearizada com transformações).
  2. Independência — Observações são independentes entre si. É violada em dados de séries temporais sem considerar autocorrelação.
  3. Homoscedasticidade — A variância dos resíduos é constante em todos os níveis dos valores previstos.
  4. Normalidade dos resíduos — Resíduos seguem uma distribuição normal. Importa mais para intervalos de confiança e testes de hipótese, menos para acurácia de previsão.
  5. Sem multicolinearidade — Features não são altamente correlacionadas entre si. Multicolinearidade inflaciona a variância dos coeficientes e torna coeficientes individuais pouco confiáveis.

Verificando as Suposições em Código

from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_california_housing
import numpy as np
 
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
model = LinearRegression()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
residuals = y_test - y_pred
 
# Check residual statistics
print(f"Residual mean:     {residuals.mean():.6f}")   # Should be near 0
print(f"Residual std:      {residuals.std():.4f}")
print(f"Residual skewness: {float(np.mean((residuals - residuals.mean())**3) / residuals.std()**3):.4f}")
 
# Check for multicollinearity (correlation matrix)
corr_matrix = np.corrcoef(X_train, rowvar=False)
print(f"\nMax feature correlation: {np.max(np.abs(corr_matrix - np.eye(corr_matrix.shape[0]))):.4f}")

Pipeline Completo: Regressão no Mundo Real

Aqui está um pipeline em estilo de produção que combina pré-processamento, engenharia de features e seleção de modelo:

from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.pipeline import Pipeline
from sklearn.datasets import fetch_california_housing
import numpy as np
 
# Load data
housing = fetch_california_housing()
X_train, X_test, y_train, y_test = train_test_split(
    housing.data, housing.target, test_size=0.2, random_state=42
)
 
# Define models to compare
models = {
    'LinearRegression': Pipeline([
        ('scaler', StandardScaler()),
        ('model', LinearRegression())
    ]),
    'Ridge (alpha=1)': Pipeline([
        ('scaler', StandardScaler()),
        ('model', Ridge(alpha=1.0))
    ]),
    'Lasso (alpha=0.01)': Pipeline([
        ('scaler', StandardScaler()),
        ('model', Lasso(alpha=0.01, max_iter=10000))
    ]),
    'Poly(2) + Ridge': Pipeline([
        ('poly', PolynomialFeatures(degree=2, include_bias=False)),
        ('scaler', StandardScaler()),
        ('model', Ridge(alpha=10.0))
    ])
}
 
# Evaluate all models
print(f"{'Model':<25} {'CV R² (mean)':>12} {'CV R² (std)':>12} {'Test R²':>10}")
print("-" * 62)
 
for name, pipeline in models.items():
    cv_scores = cross_val_score(pipeline, X_train, y_train, cv=5, scoring='r2')
    pipeline.fit(X_train, y_train)
    test_r2 = pipeline.score(X_test, y_test)
    print(f"{name:<25} {cv_scores.mean():>12.4f} {cv_scores.std():>12.4f} {test_r2:>10.4f}")

Explorando Resultados de Regressão com PyGWalker

Depois de treinar seu modelo, entender padrões de previsão é crítico. O PyGWalker (opens in a new tab) permite explorar visualmente resíduos, importâncias de features e relações entre previsto vs real por meio de uma interface interativa de arrastar e soltar no Jupyter:

import pandas as pd
import pygwalker as pyg
 
# Build a results DataFrame
results = pd.DataFrame(housing.data[len(X_train):], columns=housing.feature_names)
results['actual'] = y_test
results['predicted'] = y_pred
results['residual'] = y_test - y_pred
results['abs_error'] = np.abs(y_test - y_pred)
 
# Launch interactive exploration
walker = pyg.walk(results)

Você pode arrastar features para os eixos, colorir por magnitude do resíduo e identificar quais segmentos dos seus dados o modelo tem mais dificuldade — tudo sem escrever código de plotagem.

Para rodar experimentos iterativamente no Jupyter, o RunCell (opens in a new tab) fornece um agente de IA que ajuda você a testar diferentes combinações de features, hiperparâmetros e etapas de pré-processamento sem reescrever manualmente as células.

FAQ

O que é LinearRegression no sklearn?

sklearn.linear_model.LinearRegression é um modelo de regressão por Ordinary Least Squares (OLS). Ele ajusta uma equação linear aos dados minimizando a soma dos quadrados das diferenças entre valores reais e previstos. É o modelo de regressão mais simples e mais interpretável no scikit-learn.

Como interpreto o score R-squared?

R-squared mede a proporção da variância na variável-alvo que é explicada pelo modelo. Um R-squared de 0.80 significa que 80% da variância é explicada. O valor 1.0 é um ajuste perfeito, 0.0 significa que o modelo não é melhor do que prever a média, e valores negativos significam que o modelo é pior do que usar apenas a média.

Quando devo usar Ridge vs Lasso vs ElasticNet?

Use Ridge quando você quer manter todas as features, mas reduzir overfitting (features multicolineares). Use Lasso quando você quer seleção automática de features (ele zera coeficientes de features irrelevantes). Use ElasticNet quando as features são correlacionadas e você quer um equilíbrio entre a estabilidade do Ridge e a esparsidade do Lasso.

LinearRegression precisa de feature scaling?

O LinearRegression básico não exige escalonamento porque a solução OLS é invariante à escala. Porém, Ridge, Lasso e ElasticNet exigem escalonamento porque suas penalidades tratam todas as magnitudes de coeficientes igualmente. Sempre escale as features antes de regressão regularizada.

Como lidar com features categóricas em regressão linear?

Converta features categóricas para números usando OneHotEncoder ou pd.get_dummies() antes de ajustar. O LinearRegression do sklearn aceita apenas entradas numéricas. Em pipelines, use ColumnTransformer para aplicar transformações diferentes em colunas numéricas e categóricas.

Qual é a diferença entre MSE e RMSE?

MSE (Mean Squared Error) é a média dos erros ao quadrado entre valores reais e previstos. RMSE (Root Mean Squared Error) é a raiz quadrada do MSE. O RMSE tem as mesmas unidades da variável-alvo, o que facilita a interpretação. Por exemplo, ao prever preços de casas em dólares, RMSE de 50.000 significa um erro médio de previsão de cerca de $50.000.

Conclusão

O LinearRegression do sklearn é o ponto de partida para qualquer tarefa de regressão em Python. Ele é rápido, interpretável e eficaz quando a relação subjacente é aproximadamente linear. Para datasets do mundo real com ruído, multicolinearidade ou muitas features, Ridge, Lasso e ElasticNet fornecem regularização que melhora a generalização. Sempre avalie com múltiplas métricas (R-squared, RMSE, MAE), use divisões treino-teste para evitar overfitting e verifique padrões nos resíduos para confirmar se as suposições do modelo se mantêm. Construa pipelines com StandardScaler e PolynomialFeatures para manter seu workflow limpo e reprodutível.

📚