Regressão do Menor Ângulo (LARS): Uma Abordagem Geométrica
Introdução ao Método LARS
A Regressão do Menor Ângulo, conhecida como Least Angle Regression (LARS), constitui um algoritmo elegante para regressão linear com seleção de features. Primordialmente, diferencia-se de métodos tradicionais por sua abordagem geométrica incremental, adicionando variáveis ao modelo de forma sequencial.
Princípio Fundamental
O LARS opera através de um processo iterativo onde, a cada passo, o algoritmo seleciona a feature que forma o menor ângulo com o resíduo atual. Surpreendentemente, esta abordagem permite calcular soluções para todos os valores de regularização de forma computacionalmente eficiente.
Intuição Geométrica
Imagine cada feature como um vetor no espaço multidimensional. O LARS inicia com predições nulas e, a cada iteração, move-se na direção que forma o menor ângulo com o vetor residual atual, até que outra feature se torne igualmente correlacionada.
Algoritmo LARS Passo a Passo
- Inicializar todos os coeficientes como zero
- Encontrar a feature mais correlacionada com o resíduo
- Mover o coeficiente na direção desta feature até que outra feature tenha correlação igual
- Continuar na direção equiangular entre as features ativas
- Repetir até que todas as features relevantes sejam incluídas
Vantagens do Método LARS
- Eficiência computacional para problemas de alta dimensionalidade
- Cálculo de todo o caminho de regularização em uma única execução
- Seleção natural de features de forma sequencial
- Estabilidade numérica superior em comparação com métodos diretos
Relação com Lasso
Inegavelmente, uma das características mais notáveis do LARS é sua conexão profunda com a regressão Lasso. Com uma modificação simples, o algoritmo LARS pode computar exatamente a solução do Lasso para todos os valores do parâmetro de regularização.
Modificação LARS-Lasso
Quando uma feature ativa torna-se não-ativa (coeficiente atinge zero), o algoritmo LARS-Lasso remove esta feature do conjunto ativo antes de continuar. Esta simples modificação produz soluções idênticas ao Lasso tradicional.
Implementação no scikit-learn
No scikit-learn, a classe Lars implementa o algoritmo básico, enquanto LassoLars combina LARS com a penalidade Lasso. Ademais, LarsCV fornece seleção automática do parâmetro via validação cruzada.
Parâmetros Principais
n_nonzero_coefs: Número máximo de coeficientes não nulosalpha: Parâmetro de regularização (para LassoLars)fit_intercept: Se deve calcular o interceptonormalize: Normalização dos dados de entrada
Exemplo Prático Comparativo
O exemplo a seguir demonstra o uso do LARS e sua comparação com outros métodos de regressão:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import Lars, LassoLars, Lasso, LinearRegression from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.metrics import mean_squared_error, r2_score from sklearn.preprocessing import StandardScaler print("=" * 60) print("COMPARAÇÃO: LARS VS OUTROS MÉTODOS DE REGRESSÃO") print("=" * 60) # Gerar dados com features correlacionadas X, y = make_regression(n_samples=150, n_features=10, n_informative=5, noise=0.2, random_state=42, effective_rank=3) # Adicionar correlação entre features X[:, 3] = X[:, 0] * 0.7 + X[:, 3] * 0.3 X[:, 7] = X[:, 1] * 0.6 + X[:, 7] * 0.4 # Normalizar os dados scaler = StandardScaler() X_scaled = scaler.fit_transform(X) y_centered = y - np.mean(y) # Dividir em treino e teste X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_centered, test_size=0.3, random_state=42) print(f"Dimensões: {X.shape[0]} amostras, {X.shape[1]} features") print(f"Features informativas: 5") # 1. Regressão Linear Ordinária print("\n1. REGRESSÃO LINEAR ORDINÁRIA") ols = LinearRegression() ols.fit(X_train, y_train) y_pred_ols = ols.predict(X_test) print(f"Coeficientes não nulos: {np.sum(ols.coef_ != 0)}/10") print(f"MSE: {mean_squared_error(y_test, y_pred_ols):.4f}") # 2. LARS Básico print("\n2. LARS (5 COEFICIENTES NÃO NULOS)") lars = Lars(n_nonzero_coefs=5) lars.fit(X_train, y_train) y_pred_lars = lars.predict(X_test) print(f"Coeficientes não nulos: {np.sum(lars.coef_ != 0)}/10") print(f"MSE: {mean_squared_error(y_test, y_pred_lars):.4f}") # 3. LassoLars print("\n3. LASSO LARS (ALPHA=0.1)") lasso_lars = LassoLars(alpha=0.1) lasso_lars.fit(X_train, y_train) y_pred_ll = lasso_lars.predict(X_test) print(f"Coeficientes não nulos: {np.sum(lasso_lars.coef_ != 0)}/10") print(f"MSE: {mean_squared_error(y_test, y_pred_ll):.4f}") # 4. Lasso Tradicional print("\n4. LASSO TRADICIONAL (ALPHA=0.1)") lasso = Lasso(alpha=0.1, max_iter=10000) lasso.fit(X_train, y_train) y_pred_lasso = lasso.predict(X_test) print(f"Coeficientes não nulos: {np.sum(lasso.coef_ != 0)}/10") print(f"MSE: {mean_squared_error(y_test, y_pred_lasso):.4f}") # Visualização comparativa plt.figure(figsize=(15, 10)) # Gráfico 1: Comparação de coeficientes plt.subplot(2, 2, 1) modelos = [ols, lars, lasso_lars, lasso] nomes = ['OLS', 'LARS', 'LassoLars', 'Lasso'] cores = ['blue', 'green', 'red', 'orange'] for i, (modelo, nome) in enumerate(zip(modelos, nomes)): plt.bar(np.arange(10) + i*0.2, modelo.coef_, width=0.18, label=nome, alpha=0.7, color=cores[i]) plt.axhline(y=0, color='black', linestyle='-', alpha=0.3) plt.xlabel('Features') plt.ylabel('Valor do Coeficiente') plt.title('Comparação dos Coeficientes') plt.xticks(np.arange(10) + 0.3, [f'F{i+1}' for i in range(10)]) plt.legend() plt.grid(True, alpha=0.3) # Gráfico 2: Caminho LARS plt.subplot(2, 2, 2) # Calcular caminho LARS completo lars_path = Lars() lars_path.fit(X_train, y_train) # Extrair coeficientes ao longo do caminho coef_path = lars_path.coef_path_ for i in range(coef_path.shape[0]): plt.plot(np.sum(np.abs(coef_path[:i+1]), axis=0), coef_path[i], label=f'F{i+1}', linewidth=2) plt.xlabel('Norma L1 dos Coeficientes') plt.ylabel('Valor do Coeficiente') plt.title('Caminho LARS - Evolução dos Coeficientes') plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(True, alpha=0.3) # Gráfico 3: Features selecionadas plt.subplot(2, 2, 3) features_selecionadas = [np.sum(m.coef_ != 0) for m in modelos] plt.bar(nomes, features_selecionadas, color=cores, alpha=0.7) plt.ylabel('Número de Features Selecionadas') plt.title('Comparação de Esparsidade') for i, v in enumerate(features_selecionadas): plt.text(i, v + 0.1, str(v), ha='center', va='bottom') plt.grid(True, alpha=0.3) # Gráfico 4: Performance plt.subplot(2, 2, 4) mse_valores = [mean_squared_error(y_test, m.predict(X_test)) for m in modelos] plt.bar(nomes, mse_valores, color=cores, alpha=0.7) plt.ylabel('Mean Squared Error') plt.title('Comparação de Performance') for i, v in enumerate(mse_valores): plt.text(i, v + 0.01, f'{v:.3f}', ha='center', va='bottom') plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() # Análise detalhada da seleção de features print("\n5. ANÁLISE DETALHADA DA SELEÇÃO") print("Feature | OLS | LARS | LassoLars | Lasso ") print("-" * 60) for i in range(10): coef_ols = ols.coef_[i] coef_lars = lars.coef_[i] coef_ll = lasso_lars.coef_[i] coef_lasso = lasso.coef_[i] print(f"F{i+1:2d} | {coef_ols:10.4f} | {coef_lars:10.4f} | {coef_ll:10.4f} | {coef_lasso:10.4f}") |
Aplicações Práticas do LARS
O método LARS é particularmente útil em cenários específicos:
- Análise exploratória de dados com muitas features
- Seleção de variáveis em problemas de alta dimensionalidade
- Computação eficiente do caminho de regularização completo
- Problemas onde a ordem de importância das features é relevante
Considerações sobre Performance
Embora o LARS seja computacionalmente eficiente para problemas com muitas features, pode tornar-se lento quando o número de amostras é muito grande. Nesses casos, métodos baseados em descida de gradiente podem ser mais apropriados.
Considerações Finais
Inegavelmente, a Regressão do Menor Ângulo representa uma contribuição significativa para o arsenal de métodos de regressão. Sua abordagem geométrica proporciona intuição valiosa sobre o processo de seleção de features.
Decerto, a conexão entre LARS e Lasso torna o método particularmente atraente para aplicações práticas. Ademais, a capacidade de computar todo o caminho de regularização em uma única execução oferece vantagens computacionais importantes.
Analogamente a outros métodos de regularização, a interpretação dos resultados requer atenção à ordem de entrada das features no modelo. Portanto, a análise do caminho LARS pode revelar insights valiosos sobre a estrutura subjacente dos dados.