Imagine que você está organizando uma biblioteca e precisa decidir como agrupar livros similares. Você pode organizar por autor (RBF kernel), por período histórico (Periódico kernel), ou por complexidade do texto (Linear kernel). Cada método revela diferentes tipos de similaridades entre os livros. No mundo dos Processos Gaussianos, os kernels são exatamente isso – funções que definem como medimos a “similaridade” entre pontos de dados, moldando completamente o comportamento e a personalidade do seu modelo.
Como isso funciona na prática?
Os kernels (ou núcleos) são o coração dos Processos Gaussianos – eles definem a função de covariância que especifica como os valores da função em pontos diferentes se relacionam. Pense no kernel como uma lente através da qual o modelo enxerga os dados: um kernel RBF assume que pontos próximos têm valores similares, criando funções suaves; um kernel periódico captura padrões que se repetem; um kernel linear modela relações lineares. A API de kernels do Scikit-Learn permite combinar, escalar e transformar esses kernels como peças de Lego, criando modelos customizados para padrões complexos do mundo real.
Mãos na massa: explorando a galeria de kernels do Scikit-Learn
|
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 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
""" Explorando a API de Kernels para Processos Gaussianos no Scikit-Learn Demonstra como diferentes kernels capturam diferentes tipos de padrões """ import numpy as np import matplotlib.pyplot as plt from sklearn.gaussian_process.kernels import (RBF, Matern, RationalQuadratic, ExpSineSquared, DotProduct, ConstantKernel, WhiteKernel) from sklearn.gaussian_process import GaussianProcessRegressor # Criando dados de exemplo com diferentes padrões def criar_dados_exemplo(): """Cria dados com múltiplos padrões para demonstrar diferentes kernels""" np.random.seed(42) x = np.linspace(0, 10, 100).reshape(-1, 1) # Padrão 1: Tendência suave + ruído y_smooth = np.sin(x.ravel()) + 0.1 * np.random.normal(size=100) # Padrão 2: Sazonalidade periódica y_periodic = np.sin(2 * np.pi * x.ravel()) + 0.1 * np.random.normal(size=100) # Padrão 3: Variações em múltiplas escalas y_multiscale = (np.sin(x.ravel()) + 0.3 * np.sin(3 * x.ravel()) + 0.1 * np.random.normal(size=100)) # Padrão 4: Tendência linear y_linear = 0.5 * x.ravel() + 0.1 * np.random.normal(size=100) return x, [y_smooth, y_periodic, y_multiscale, y_linear] x, padroes_y = criar_dados_exemplo() nomes_padroes = ['Suave', 'Periódico', 'Múltiplas Escalas', 'Linear'] # Definindo uma galeria de kernels kernels = { 'RBF': RBF(length_scale=1.0), 'RBF Otimizado': RBF(), 'Matern (ν=1.5)': Matern(length_scale=1.0, nu=1.5), 'Matern (ν=2.5)': Matern(length_scale=1.0, nu=2.5), 'Periódico': ExpSineSquared(length_scale=1.0, periodicity=1.0), 'RationalQuadratic': RationalQuadratic(length_scale=1.0, alpha=1.0), 'Linear': DotProduct(sigma_0=1.0), 'Composto (RBF + Periódico)': RBF(length_scale=1.0) * ExpSineSquared(length_scale=1.0, periodicity=1.0) } print("=== GALERIA DE KERNELS DO SCIKIT-LEARN ===\n") # Testando cada kernel em diferentes padrões fig, axes = plt.subplots(len(kernels), len(padroes_y), figsize=(20, 16)) for i, (nome_kernel, kernel) in enumerate(kernels.items()): print(f"Kernel: {nome_kernel}") for j, (y, nome_padrao) in enumerate(zip(padroes_y, nomes_padroes)): ax = axes[i, j] try: # Criando e treinando GPR com o kernel gpr = GaussianProcessRegressor(kernel=kernel, alpha=0.1, random_state=42) gpr.fit(x, y) # Fazendo previsões x_pred = np.linspace(0, 10, 200).reshape(-1, 1) y_pred, sigma = gpr.predict(x_pred, return_std=True) # Plotando resultados ax.plot(x, y, 'ro', alpha=0.6, markersize=4, label='Dados') ax.plot(x_pred, y_pred, 'b-', linewidth=2, label='Previsão') ax.fill_between(x_pred.ravel(), y_pred - 1.96*sigma, y_pred + 1.96*sigma, alpha=0.2, color='blue', label='Incerteza') # Informações do kernel otimizado if hasattr(gpr.kernel_, 'theta'): kernel_info = f"θ={gpr.kernel_.theta[0]:.2f}" if len(gpr.kernel_.theta) == 1 else "θ otimizado" else: kernel_info = "Parâmetros fixos" ax.set_title(f'{nome_kernel}\n{nome_padrao}\n{kernel_info}', fontsize=9) ax.grid(True, alpha=0.3) # Apenas primeira coluna tem labels y if j == 0: ax.set_ylabel('y') # Apenas última linha tem labels x if i == len(kernels) - 1: ax.set_xlabel('x') except Exception as e: ax.text(0.5, 0.5, f'Erro:\n{str(e)}', ha='center', va='center', transform=ax.transAxes, fontsize=8) ax.set_title(f'{nome_kernel}\n{nome_padrao}\nERRO', fontsize=9) plt.tight_layout() plt.show() # Demonstração da API de composição de kernels print("\n=== API DE COMPOSIÇÃO DE KERNELS ===") # Kernel constante para escala k_const = ConstantKernel(constant_value=1.0, constant_value_bounds=(1e-5, 1e5)) # Kernels base k_rbf = RBF(length_scale=1.0, length_scale_bounds=(1e-2, 1e2)) k_periodic = ExpSineSquared(length_scale=1.0, periodicity=1.0, periodicity_bounds=(1e-2, 1e2)) k_linear = DotProduct(sigma_0=1.0, sigma_0_bounds=(1e-5, 1e5)) k_noise = WhiteKernel(noise_level=0.1, noise_level_bounds=(1e-5, 1e2)) # Combinando kernels kernel_complexo = ( k_const * k_rbf + # Componente suave k_const * k_periodic + # Componente periódico k_linear + # Componente linear k_noise # Ruído ) print("Kernel complexo construído:") print(f"Expressão: {kernel_complexo}") print(f"Hiperparâmetros: {kernel_complexo.hyperparameters}") # Testando o kernel complexo em dados com múltiplos padrões x_complex = np.linspace(0, 10, 50).reshape(-1, 1) y_complex = (np.sin(x_complex.ravel()) + # Padrão suave 0.5 * np.sin(3 * x_complex.ravel()) + # Padrão periódico 0.1 * x_complex.ravel() + # Tendência linear 0.1 * np.random.normal(size=50)) # Ruído gpr_complex = GaussianProcessRegressor(kernel=kernel_complexo, random_state=42) gpr_complex.fit(x_complex, y_complex) print(f"\nKernel complexo otimizado:") print(f"Antes: {kernel_complexo}") print(f"Depois: {gpr_complex.kernel_}") print(f"Log-marginal-likelihood: {gpr_complex.log_marginal_likelihood():.2f}") # Visualizando o kernel complexo plt.figure(figsize=(12, 4)) # Plot das previsões plt.subplot(1, 2, 1) x_pred_complex = np.linspace(0, 10, 100).reshape(-1, 1) y_pred_complex, sigma_complex = gpr_complex.predict(x_pred_complex, return_std=True) plt.plot(x_complex, y_complex, 'ro', alpha=0.8, label='Dados') plt.plot(x_pred_complex, y_pred_complex, 'b-', label='Previsão') plt.fill_between(x_pred_complex.ravel(), y_pred_complex - 1.96*sigma_complex, y_pred_complex + 1.96*sigma_complex, alpha=0.2, label='Incerteza 95%') plt.title('Kernel Complexo: Capturando Múltiplos Padrões') plt.xlabel('x') plt.ylabel('y') plt.legend() plt.grid(True, alpha=0.3) # Plot da matriz de covariância do kernel plt.subplot(1, 2, 2) x_cov = np.linspace(0, 5, 50).reshape(-1, 1) ponto_fixo = np.array([[2.5]]) K = gpr_complex.kernel_(x_cov, ponto_fixo) plt.plot(x_cov, K, 'g-', linewidth=2) plt.axvline(x=2.5, color='red', linestyle='--', alpha=0.7, label='Ponto de referência') plt.title('Função de Covariância do Kernel\n(Similaridade com ponto x=2.5)') plt.xlabel('x') plt.ylabel('Covariância') plt.legend() plt.grid(True, alpha=0.3) plt.tight_layout() plt.show() |
Os detalhes que fazem diferença
A escolha do kernel é provavelmente a decisão mais importante ao usar Processos Gaussianos. O kernel RBF é um ótimo ponto de partida para a maioria dos problemas, criando funções suaves e infinitamente diferenciáveis. Contudo, o kernel Matern oferece mais controle sobre a suavidade através do parâmetro ν – valores menores criam funções mais irregulares, valores maiores criam funções mais suaves. A API do Scikit-Learn permite operações algébricas entre kernels: adição combina padrões, multiplicação cria interações, e exponenciação controla a escala. Definir bounds realistas para os hiperparâmetros é crucial para evitar overfitting e garantir que a otimização encontre soluções significativas.
- RBF: Padrão ouro para funções suaves, infinitamente diferenciável
- Matern: Controle explícito da suavidade via parâmetro ν
- ExpSineSquared: Ideal para padrões periódicos e sazonais
- Operações: + combina, × interage, ** escala kernels
- Bounds: Sempre defina limites realistas para hiperparâmetros
Perguntas que os iniciantes fazem
Você deve estar se perguntando: “Como escolher o kernel certo para meu problema?” Comece com RBF para problemas gerais e observe os resíduos – padrões periódicos nos resíduos sugerem ExpSineSquared, tendências lineares sugerem DotProduct. Uma confusão comum é pensar que kernels mais complexos são sempre melhores – na verdade, kernels simples frequentemente generalizam melhor. Outra dúvida frequente: “Preciso sempre otimizar os hiperparâmetros?” Sim! Deixar o Scikit-Learn otimizar os parâmetros via máxima verossimilhança marginal é essencial para bons resultados, mas defina bounds sensatos baseados no seu domínio.
Para onde ir agora?
Experimente criar kernels customizados combinando os kernels básicos para capturar padrões específicos do seu domínio. Use a log-verossimilhança marginal para comparar diferentes kernels objetivamente. Visualize a matriz de covariância para entender como cada kernel “enxerga” similaridades entre pontos. O momento “aha!” acontece quando você percebe que kernels diferentes revelam diferentes aspectos dos seus dados, como diferentes lentes fotográficas revelam diferentes características de uma paisagem.
Assuntos relacionados
Para dominar kernels de GP, estude:
- Teoria de kernels: propriedades de funções positivas definidas
- Espaços de Hilbert: fundamentos matemáticos dos métodos de kernel
- Processos estocásticos: covariância e estrutura de dependência
- Otimização de hiperparâmetros: métodos baseados em gradiente e grid search
- Teoria espectral: decomposição de operadores de covariância