'''
Aplicação da Regressão Polinomial para Modelagem Não-Linear
CÓDIGO CORRIGIDO - Problema com número de labels no gráfico
'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.datasets import make_regression
# Exemplo 1: Regressão Polinomial com uma feature
print("=== REGRESSÃO POLINOMIAL - UMA FEATURE ===")
# Gerar dados não-lineares
np.random.seed(42)
n_samples = 200
X_single = np.random.uniform(-3, 3, n_samples).reshape(-1, 1)
y_single = 2 * X_single.ravel() - 0.5 * X_single.ravel()**2 + 0.1 * X_single.ravel()**3 + np.random.normal(0, 0.5, n_samples)
print(f"Dimensões: X {X_single.shape}, y {y_single.shape}")
# Dividir em treino e teste
X_train_single, X_test_single, y_train_single, y_test_single = train_test_split(
X_single, y_single, test_size=0.3, random_state=42)
# Criar pipelines para diferentes graus polinomiais
degrees = [1, 2, 3, 4, 5, 6]
pipelines = {}
scores = {}
for degree in degrees:
# Pipeline com regressão linear
pipeline = Pipeline([
('poly', PolynomialFeatures(degree=degree, include_bias=False)),
('linear', LinearRegression())
])
pipeline.fit(X_train_single, y_train_single)
y_pred = pipeline.predict(X_test_single)
mse = mean_squared_error(y_test_single, y_pred)
r2 = r2_score(y_test_single, y_pred)
pipelines[degree] = pipeline
scores[degree] = {'mse': mse, 'r2': r2}
print(f"Grau {degree}: MSE = {mse:.4f}, R² = {r2:.4f}")
# Exemplo 2: Regressão Polinomial com múltiplas features
print(f"\n=== REGRESSÃO POLINOMIAL - MÚLTIPLAS FEATURES ===")
# Gerar dataset com relacionamentos não-lineares
X_multi, y_multi = make_regression(n_samples=1000, n_features=3,
n_informative=3, noise=10,
random_state=42)
# Adicionar não-linearidade
X_multi[:, 0] = X_multi[:, 0] + 0.1 * X_multi[:, 0]**2
X_multi[:, 1] = X_multi[:, 1] * X_multi[:, 2] # Termo de interação
X_train_multi, X_test_multi, y_train_multi, y_test_multi = train_test_split(
X_multi, y_multi, test_size=0.3, random_state=42)
# Comparar diferentes abordagens
models = {
'Linear': LinearRegression(),
'Poly2 + Linear': Pipeline([
('poly', PolynomialFeatures(degree=2)),
('linear', LinearRegression())
]),
'Poly2 + Ridge': Pipeline([
('poly', PolynomialFeatures(degree=2)),
('ridge', Ridge(alpha=1.0))
]),
'Poly3 + Linear': Pipeline([
('poly', PolynomialFeatures(degree=3)),
('linear', LinearRegression())
])
}
multi_results = {}
for name, model in models.items():
model.fit(X_train_multi, y_train_multi)
y_pred = model.predict(X_test_multi)
mse = mean_squared_error(y_test_multi, y_pred)
r2 = r2_score(y_test_multi, y_pred)
multi_results[name] = {'mse': mse, 'r2': r2}
print(f"{name:15}: MSE = {mse:.2f}, R² = {r2:.4f}")
# Encontrar o melhor grau por validação cruzada
print(f"\n=== SELEÇÃO DO MELHOR GRAU ===")
degree_range = range(1, 8)
cv_scores = []
best_degree = 3 # Valor padrão caso haja problemas
for degree in degree_range:
try:
pipeline = Pipeline([
('poly', PolynomialFeatures(degree=degree)),
('linear', LinearRegression())
])
scores_cv = cross_val_score(pipeline, X_single, y_single,
cv=5, scoring='neg_mean_squared_error')
cv_scores.append(-scores_cv.mean())
print(f"Grau {degree}: MSE CV = {-scores_cv.mean():.4f}")
except Exception as e:
cv_scores.append(float('inf'))
print(f"Grau {degree}: Erro - {e}")
if cv_scores and min(cv_scores) != float('inf'):
best_degree = degree_range[np.argmin(cv_scores)]
else:
# Usar o grau com melhor performance no teste
best_degree = min(scores.items(), key=lambda x: x[1]['mse'])[0]
print(f"Melhor grau selecionado: {best_degree}")
# Visualização dos resultados
plt.figure(figsize=(18, 12))
# Gráfico 1: Comparação de diferentes graus polinomiais (uma feature)
plt.subplot(3, 4, 1)
x_plot = np.linspace(-3, 3, 300).reshape(-1, 1)
plt.scatter(X_test_single, y_test_single, alpha=0.6, label='Dados de teste', color='gray')
for degree in [1, 2, 3, 6]:
y_plot = pipelines[degree].predict(x_plot)
plt.plot(x_plot, y_plot, label=f'Grau {degree}', linewidth=2)
plt.xlabel('Feature X')
plt.ylabel('Target y')
plt.title('Regressão Polinomial - Diferentes Graus')
plt.legend()
plt.grid(True, alpha=0.3)
# Gráfico 2: MSE vs Grau do Polinômio
plt.subplot(3, 4, 2)
mses = [scores[degree]['mse'] for degree in degrees]
plt.plot(degrees, mses, 'o-', linewidth=2, markersize=8)
plt.xlabel('Grau do Polinômio')
plt.ylabel('MSE')
plt.title('Erro vs Complexidade do Modelo')
plt.grid(True, alpha=0.3)
# Gráfico 3: R² vs Grau do Polinômio
plt.subplot(3, 4, 3)
r2s = [scores[degree]['r2'] for degree in degrees]
plt.plot(degrees, r2s, 's-', linewidth=2, markersize=8, color='green')
plt.xlabel('Grau do Polinômio')
plt.ylabel('R²')
plt.title('R² vs Complexidade do Modelo')
plt.grid(True, alpha=0.3)
# Gráfico 4: Número de features geradas
plt.subplot(3, 4, 4)
n_features_generated = []
for degree in degrees:
poly = PolynomialFeatures(degree=degree)
poly.fit(X_train_single)
n_features_generated.append(poly.transform(X_train_single).shape[1])
plt.plot(degrees, n_features_generated, '^-', linewidth=2, markersize=8, color='red')
plt.xlabel('Grau do Polinômio')
plt.ylabel('Número de Features')
plt.title('Expansão de Features vs Grau')
plt.grid(True, alpha=0.3)
# Gráfico 5: Comparação de modelos (múltiplas features)
plt.subplot(3, 4, 5)
model_names = list(multi_results.keys())
mses_multi = [multi_results[name]['mse'] for name in model_names]
plt.bar(model_names, mses_multi, alpha=0.7)
plt.ylabel('MSE')
plt.title('Comparação de Modelos - Múltiplas Features')
plt.xticks(rotation=45)
for i, v in enumerate(mses_multi):
plt.text(i, v + 0.5, f'{v:.1f}', ha='center', va='bottom')
# Gráfico 6: R² dos modelos (múltiplas features)
plt.subplot(3, 4, 6)
r2s_multi = [multi_results[name]['r2'] for name in model_names]
plt.bar(model_names, r2s_multi, alpha=0.7, color='green')
plt.ylabel('R²')
plt.title('R² dos Modelos - Múltiplas Features')
plt.xticks(rotation=45)
for i, v in enumerate(r2s_multi):
plt.text(i, v + 0.01, f'{v:.3f}', ha='center', va='bottom')
# Gráfico 7: Validação cruzada para seleção do grau ótimo
plt.subplot(3, 4, 7)
if cv_scores and min(cv_scores) != float('inf'):
plt.plot(degree_range, cv_scores, 'o-', linewidth=2)
plt.axvline(x=best_degree, color='red', linestyle='--',
label=f'Melhor grau: {best_degree}')
plt.xlabel('Grau do Polinômio')
plt.ylabel('MSE (Validação Cruzada)')
plt.title('Seleção do Grau por Validação Cruzada')
plt.legend()
plt.grid(True, alpha=0.3)
else:
plt.text(0.5, 0.5, 'Validação cruzada\nnão disponível',
ha='center', va='center', transform=plt.gca().transAxes)
plt.title('Validação Cruzada - Erro')
# Gráfico 8: Overfitting - Treino vs Teste
plt.subplot(3, 4, 8)
train_scores = []
test_scores = []
for degree in degrees:
pipeline = Pipeline([
('poly', PolynomialFeatures(degree=degree)),
('linear', LinearRegression())
])
pipeline.fit(X_train_single, y_train_single)
train_pred = pipeline.predict(X_train_single)
test_pred = pipeline.predict(X_test_single)
train_mse = mean_squared_error(y_train_single, train_pred)
test_mse = mean_squared_error(y_test_single, test_pred)
train_scores.append(train_mse)
test_scores.append(test_mse)
plt.plot(degrees, train_scores, 'o-', label='Treino', linewidth=2)
plt.plot(degrees, test_scores, 's-', label='Teste', linewidth=2)
plt.xlabel('Grau do Polinômio')
plt.ylabel('MSE')
plt.title('Overfitting: Treino vs Teste')
plt.legend()
plt.grid(True, alpha=0.3)
# Gráfico 9: Regularização com Ridge (controle de overfitting)
plt.subplot(3, 4, 9)
alphas = [0.001, 0.01, 0.1, 1, 10, 100, 1000]
degree_fixed = 6 # Grau alto que provavelmente overfita
ridge_scores = []
for alpha in alphas:
try:
pipeline = Pipeline([
('poly', PolynomialFeatures(degree=degree_fixed)),
('ridge', Ridge(alpha=alpha))
])
scores_cv = cross_val_score(pipeline, X_single, y_single,
cv=5, scoring='neg_mean_squared_error')
ridge_scores.append(-scores_cv.mean())
except:
ridge_scores.append(float('inf'))
if ridge_scores and min(ridge_scores) != float('inf'):
best_alpha = alphas[np.argmin(ridge_scores)]
plt.semilogx(alphas, ridge_scores, 'o-', linewidth=2)
plt.axvline(x=best_alpha, color='red', linestyle='--',
label=f'Melhor alpha: {best_alpha}')
plt.xlabel('Alpha (Regularização)')
plt.ylabel('MSE (Validação Cruzada)')
plt.title('Regularização Ridge - Controle de Overfitting')
plt.legend()
plt.grid(True, alpha=0.3)
else:
plt.text(0.5, 0.5, 'Regularização\nnão disponível',
ha='center', va='center', transform=plt.gca().transAxes)
plt.title('Regularização - Erro')
# Gráfico 10: Features geradas pelo PolynomialFeatures (grau 2)
plt.subplot(3, 4, 10)
try:
poly = PolynomialFeatures(degree=2, include_bias=False)
X_poly = poly.fit_transform(X_multi[:5, :]) # Apenas primeiras 5 amostras
plt.imshow(X_poly, aspect='auto', cmap='viridis')
plt.colorbar()
plt.xlabel('Features Polinomiais')
plt.ylabel('Amostras')
plt.title('Matriz de Features Polinomiais (Grau 2)')
except:
plt.text(0.5, 0.5, 'Visualização de features\nnão disponível',
ha='center', va='center', transform=plt.gca().transAxes)
plt.title('Features Polinomiais - Erro')
# Gráfico 11: Importância dos termos polinomiais (CORRIGIDO)
plt.subplot(3, 4, 11)
try:
best_pipeline = Pipeline([
('poly', PolynomialFeatures(degree=best_degree)),
('linear', LinearRegression())
])
best_pipeline.fit(X_train_single, y_train_single)
coefficients = best_pipeline.named_steps['linear'].coef_
# CORREÇÃO: Garantir que o número de labels corresponde ao número de coeficientes
n_coefficients = len(coefficients)
feature_names = [f'x^{i+1}' for i in range(n_coefficients)]
plt.bar(range(n_coefficients), coefficients, alpha=0.7)
plt.axhline(y=0, color='black', linestyle='-', alpha=0.5)
plt.xlabel('Termo Polinomial')
plt.ylabel('Valor do Coeficiente')
plt.title(f'Coeficientes (Grau {best_degree})')
# CORREÇÃO: Usar apenas se o número de coeficientes for razoável para visualização
if n_coefficients <= 10:
plt.xticks(range(n_coefficients), feature_names, rotation=45)
else:
plt.xticks(range(0, n_coefficients, max(1, n_coefficients//10)),
rotation=45)
except Exception as e:
plt.text(0.5, 0.5, f'Erro nos coeficientes:\n{str(e)}',
ha='center', va='center', transform=plt.gca().transAxes, fontsize=8)
plt.title('Coeficientes - Erro')
# Gráfico 12: Resíduos do modelo polinomial
plt.subplot(3, 4, 12)
try:
best_model = pipelines.get(best_degree, pipelines[3]) # Fallback para grau 3
y_pred_best = best_model.predict(X_test_single)
residuals = y_test_single - y_pred_best
plt.scatter(y_pred_best, residuals, alpha=0.6)
plt.axhline(y=0, color='red', linestyle='--', alpha=0.7)
plt.xlabel('Valores Preditos')
plt.ylabel('Resíduos')
plt.title('Análise de Resíduos - Modelo Polinomial')
plt.grid(True, alpha=0.3)
except:
plt.text(0.5, 0.5, 'Análise de resíduos\nnão disponível',
ha='center', va='center', transform=plt.gca().transAxes)
plt.title('Resíduos - Erro')
plt.tight_layout()
plt.show()
# Análise detalhada das features polinomiais
print(f"\n=== ANÁLISE DETALHADA DAS FEATURES POLINOMIAIS ===")
# Mostrar features geradas para grau 2 com 2 features de exemplo
try:
X_example = np.array([[1, 2], [3, 4]])
poly = PolynomialFeatures(degree=2, include_bias=True)
X_poly_example = poly.fit_transform(X_example)
print(f"\nExemplo de expansão polinomial (grau 2):")
print(f"Features originais:\n{X_example}")
print(f"Features polinomiais (com bias):")
print(f"Dimensões: {X_poly_example.shape}")
print(f"Número de features geradas: {X_poly_example.shape[1]}")
except Exception as e:
print(f"Erro na análise de features: {e}")
# Análise do melhor modelo
print(f"\n=== MELHOR MODELO ENCONTRADO ===")
print(f"Melhor grau polinomial: {best_degree}")
print(f"MSE do melhor modelo: {scores[best_degree]['mse']:.4f}")
print(f"R² do melhor modelo: {scores[best_degree]['r2']:.4f}")
# Comparação com modelo linear simples
try:
linear_model = LinearRegression()
linear_model.fit(X_train_single, y_train_single)
y_pred_linear = linear_model.predict(X_test_single)
mse_linear = mean_squared_error(y_test_single, y_pred_linear)
improvement = (mse_linear - scores[best_degree]['mse']) / mse_linear * 100
print(f"Melhoria sobre modelo linear: {improvement:.1f}%")
except:
print("Não foi possível calcular a melhoria sobre modelo linear")
# Resumo final
print(f"\n=== RESUMO FINAL ===")
print(f"A regressão polinomial mostrou melhor performance que o modelo linear")
print(f"O grau {best_degree} apresentou o melhor equilíbrio entre bias e variância")
print(f"Expansão polinomial é eficaz para capturar relacionamentos não-lineares")