Anteriormente exploramos diversas implementações do Lasso. Analogamente, o LassoLars oferece uma abordagem computacionalmente eficiente para resolver problemas Lasso usando o algoritmo LARS (Least Angle Regression).
Conceito Fundamental do LassoLars
Primordialmente, o LassoLars combina o algoritmo LARS com a penalidade L1 do Lasso. Decerto, ao contrário de métodos baseados em otimização convexa, o LARS constrói a solução de forma incremental, adicionando uma feature por vez ao modelo.
Conforme a documentação do scikit-learn, o LassoLars é computacionalmente eficiente quando o número de features é muito maior que o número de amostras. Similarmente ao Lasso tradicional, ele produz soluções esparsas, mas com uma abordagem algorítmica diferente.
O Algoritmo LARS
O algoritmo LARS opera através dos seguintes passos:
- Começa com todos coeficientes iguais a zero
- Encontra a feature mais correlacionada com o resíduo
- Move o coeficiente na direção do sinal da correlação
- Para quando outra feature tem correlação igual com o resíduo
- Adiciona essa feature ao conjunto ativo e continua
Características Principais
Inegavelmente, o LassoLars possui propriedades únicas que o distinguem de outras implementações:
- Caminho de solução completo: Computa todo o caminho de regularização de uma vez
- Eficiência numérica: Mais rápido que métodos baseados em otimização para p >> n
- Solução exata: Fornece solução exata em cada passo, não aproximada
- Seleção de variáveis: Mantém a capacidade de zerar coeficientes do Lasso
Vantagens sobre Lasso Tradicional
Embora ambos resolvam o mesmo problema, o LassoLars oferece benefícios específicos:
- Eficiência: Mais rápido quando número de features é grande
- Caminho completo: Obtém soluções para todos valores de regularização
- Estabilidade numérica: Menos sensível a problemas numéricos
- Interpretabilidade: Ordem de entrada das features é informativa
Exemplo Prático: LassoLars em Ação
Ademais, vejamos um exemplo completo demonstrando o uso do LassoLars:
|
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 |
print(__doc__) # Autor: Fabian Pedregosa <fabian.pedregosa@inria.fr> # Alexandre Gramfort <alexandre.gramfort@inria.fr> # Licença: cláusula BSD 3 import numpy as np import matplotlib.pyplot as plt from sklearn import linear_model from sklearn import datasets diabetes = datasets.load_diabetes() X = diabetes.data y = diabetes.target print("Calculando caminho de regularização usando o LARS...") _, _, coefs = linear_model.lars_path(X, y, method='lasso', verbose=True) xx = np.sum(np.abs(coefs.T), axis=1) xx /= xx[-1] plt.figure(figsize=(12, 8)) plt.plot(xx, coefs.T) ymin, ymax = plt.ylim() plt.vlines(xx, ymin, ymax, linestyle='dashed', alpha=0.3) plt.xlabel('|coef| / max|coef|') plt.ylabel('Coeficientes') plt.title('Caminho LASSO - Dataset Diabetes') plt.axis('tight') plt.grid(True, alpha=0.3) plt.show() # Adicionando análise adicional print(f"\n--- Informações do Dataset Diabetes ---") print(f"Número de amostras: {X.shape[0]}") print(f"Número de features: {X.shape[1]}") print(f"Features: {diabetes.feature_names}") # Criar gráficos adicionais para melhor compreensão plt.figure(figsize=(15, 5)) # Gráfico 1: Caminho LASSO com cores diferentes para cada feature plt.subplot(1, 3, 1) colors = plt.cm.Set1(np.linspace(0, 1, coefs.shape[0])) for i, color in enumerate(colors): plt.plot(xx, coefs[i], color=color, label=diabetes.feature_names[i] if i < len(diabetes.feature_names) else f'Feature {i}') plt.xlabel('|coef| / max|coef|') plt.ylabel('Coeficientes') plt.title('Caminho LASSO - Features Coloridas') plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left') plt.grid(True, alpha=0.3) # Gráfico 2: Ordem de entrada das features no caminho LARS plt.subplot(1, 3, 2) # Calcular quando cada feature entra no modelo active_features = [] for i in range(coefs.shape[1]): active = np.where(coefs[:, i] != 0)[0] for feat in active: if feat not in active_features: active_features.append(feat) plt.bar(range(len(active_features)), [i+1 for i in range(len(active_features))]) plt.xticks(range(len(active_features)), [diabetes.feature_names[i] for i in active_features], rotation=45) plt.ylabel('Ordem de Entrada') plt.title('Ordem de Seleção das Features') # Gráfico 3: Valores finais dos coeficientes plt.subplot(1, 3, 3) final_coefs = coefs[:, -1] colors = ['red' if coef != 0 else 'blue' for coef in final_coefs] bars = plt.bar(diabetes.feature_names, final_coefs, color=colors, alpha=0.7) plt.axhline(y=0, color='black', linestyle='-', alpha=0.5) plt.ylabel('Valor Final do Coeficiente') plt.title('Coeficientes Finais no Caminho LASSO') plt.xticks(rotation=45) for bar, coef in zip(bars, final_coefs): if coef != 0: plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + (0.1 if bar.get_height() > 0 else -0.3), f'{coef:.2f}', ha='center', va='bottom' if bar.get_height() > 0 else 'top', fontsize=8) plt.tight_layout() plt.show() # Análise estatística print(f"\n--- Análise do Caminho LASSO ---") print(f"Número total de passos no caminho: {coefs.shape[1]}") print(f"Features selecionadas no final: {np.sum(final_coefs != 0)} de {len(final_coefs)}") print(f"Features zeradas: {np.sum(final_coefs == 0)}") # Mostrar a ordem de entrada das features print(f"\nOrdem de entrada das features no modelo:") for i, feat_idx in enumerate(active_features): print(f"{i+1}º: {diabetes.feature_names[feat_idx]}") # Valores dos coeficientes em diferentes pontos do caminho print(f"\n--- Valores dos Coeficientes em Diferentes Pontos ---") checkpoints = [0, coefs.shape[1]//4, coefs.shape[1]//2, coefs.shape[1]-1] for checkpoint in checkpoints: print(f"\nPonto {checkpoint+1}/{coefs.shape[1]} (|coef|/max|coef| = {xx[checkpoint]:.3f}):") for i, name in enumerate(diabetes.feature_names): if coefs[i, checkpoint] != 0: print(f" {name}: {coefs[i, checkpoint]:.4f}") |
Casos de Uso Recomendados
O LassoLars é particularmente eficaz em:
- Alta dimensionalidade: Quando número de features é muito maior que número de amostras (p >> n)
- Seleção de variáveis: Quando a ordem de importância das features é relevante
- Análise exploratória: Para entender o caminho de solução completo
- Problemas computacionalmente intensivos: Onde eficiência é crucial
Considerações Práticas
Algumas recomendações importantes para uso eficaz:
- Use LassoLars quando p >> n para melhor eficiência
- Considere LassoLarsIC para seleção automática do parâmetro alpha
- O parâmetro max_iter controla o número máximo de iterações/features
- Para problemas com p < n, o Lasso tradicional pode ser suficiente
Variantes do LARS
O scikit-learn oferece várias variantes do algoritmo:
- Lars: Versão sem penalidade L1 (regressão por ângulos mínimos)
- LassoLars: Combinação de LARS com penalidade L1
- LassoLarsIC: Com critério de informação para seleção de modelo
Enfim, o LassoLars representa uma abordagem algorítmica elegante e eficiente para problemas Lasso, especialmente em cenários de alta dimensionalidade onde a eficiência computacional e a interpretabilidade do caminho de solução são importantes.
Referência: https://scikit-learn.org/0.21/modules/linear_model.html#lars-lasso