Aller au contenu

Sélection des Noyaux pour l'Optimisation BoTorch

Introduction

Le choix du noyau (kernel) est crucial dans les processus gaussiens et l'optimisation bayésienne. Le noyau définit la fonction de similarité entre les points d'entrée et influence directement la qualité de la modélisation et de l'optimisation.

Types de Noyaux Disponibles

1. Noyau Mixte ("mixed") - Recommandé par défaut

Principe : Combine automatiquement des noyaux adaptés aux variables discrètes et continues.

Avantages : - Adapté automatiquement au type de variables - Bon compromis entre performance et robustesse - Gère intelligemment les variables discrètes et continues

Utilisation :

results = botorch_multi_objective_optimizer_kernel(
    # ... autres paramètres ...
    kernel_type="mixed"
)

Comportement : - Variables discrètes : RBF avec lengthscale court - Variables continues : Matern 5/2 avec ARD - Combinaison multiplicative des noyaux

2. Noyau Matern ("matern")

Principe : Noyau Matern 5/2 avec détermination automatique de la pertinence (ARD).

Avantages : - Excellent pour les variables continues - Moins lisse que RBF, capture mieux les variations locales - ARD permet d'apprendre l'importance relative de chaque variable

Utilisation :

results = botorch_multi_objective_optimizer_kernel(
    # ... autres paramètres ...
    kernel_type="matern"
)

Caractéristiques : - Paramètre nu=2.5 (Matern 5/2) - ARD activé pour toutes les dimensions - Bon pour les fonctions avec des dérivées continues

3. Noyau RBF ("rbf")

Principe : Noyau à base radiale (Radial Basis Function) avec ARD.

Avantages : - Très lisse, bon pour beaucoup de types de fonctions - Robuste et stable - Convergence souvent plus rapide

Utilisation :

results = botorch_multi_objective_optimizer_kernel(
    # ... autres paramètres ...
    kernel_type="rbf"
)

Caractéristiques : - Fonction exponentielle quadratique - ARD activé pour toutes les dimensions - Excellent pour les fonctions lisses

4. Noyau Catégorique ("categorical")

Principe : Noyau spécialisé pour les variables discrètes avec lengthscales courts.

Avantages : - Optimisé pour les variables discrètes - Traite les catégories comme des points distincts - Sensible aux différences entre catégories

Utilisation :

results = botorch_multi_objective_optimizer_kernel(
    # ... autres paramètres ...
    kernel_type="categorical"
)

Caractéristiques : - RBF avec lengthscale court (0.1) - Rend les catégories "éloignées" dans l'espace du noyau - Idéal pour les variables avec peu de valeurs possibles

Recommandations par Type de Problème

Problèmes avec Variables Discrètes Dominantes

# Beaucoup de variables discrètes (matériaux, systèmes, etc.)
kernel_type = "categorical"  # ou "mixed"

Problèmes avec Variables Continues Dominantes

# Variables continues (épaisseurs, températures, etc.)
kernel_type = "matern"  # ou "rbf"

Problèmes Mixtes (Recommandé)

# Mélange de variables discrètes et continues
kernel_type = "mixed"  # Choix par défaut

Problèmes de Convergence Lente

# Si l'optimisation converge lentement
kernel_type = "rbf"  # Plus lisse, convergence plus rapide

Comparaison des Performances

Critère Mixed Matern RBF Categorical
Variables Discrètes ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐
Variables Continues ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐
Convergence ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
Robustesse ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
Facilité d'utilisation ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐

Exemple de Comparaison

#!/usr/bin/env python3
"""
Exemple de comparaison des noyaux
"""

from oreni.optim.botorch_optimization import botorch_multi_objective_optimizer_kernel

# Configuration de base
config = {
    "function": Simuls.compute_cost_functions,
    "decision_space": decision_space,
    "uncertain_space": uncertain_space,
    "function_labels": ["Cost", "Emissions", "Comfort"],
    "n_initial_points": 10,
    "n_optimization_iterations": 20,
    "n_uncs": 5
}

# Test de différents noyaux
kernels = ["mixed", "matern", "rbf", "categorical"]
results = {}

for kernel in kernels:
    print(f"Testing kernel: {kernel}")
    results[kernel] = botorch_multi_objective_optimizer_kernel(
        **config,
        kernel_type=kernel
    )

Paramètres Avancés

Ajustement des Lengthscales

Pour un contrôle plus fin, vous pouvez modifier les lengthscales dans le code :

# Dans _create_categorical_kernel
kernel.base_kernel.lengthscale = torch.ones_like(kernel.base_kernel.lengthscale) * 0.1

# Pour des variables discrètes avec plus de valeurs
kernel.base_kernel.lengthscale = torch.ones_like(kernel.base_kernel.lengthscale) * 0.05

Combinaison de Noyaux

Pour des problèmes complexes, vous pouvez créer des noyaux personnalisés :

# Exemple de noyau personnalisé
from gpytorch.kernels import MaternKernel, RBFKernel, ScaleKernel

# Noyau pour variables continues
continuous_kernel = ScaleKernel(MaternKernel(nu=2.5, ard_num_dims=3))

# Noyau pour variables discrètes
discrete_kernel = ScaleKernel(RBFKernel(ard_num_dims=2))

# Combinaison multiplicative
combined_kernel = continuous_kernel * discrete_kernel

Diagnostic et Dépannage

Problèmes de Convergence

# Si l'optimisation ne converge pas
kernel_type = "rbf"  # Plus stable
raw_samples = 1024   # Plus d'échantillons
num_restarts = 20    # Plus de redémarrages

Overfitting

# Si le modèle overfit
kernel_type = "matern"  # Moins lisse
# Ou réduire n_initial_points

Underfitting

# Si le modèle underfit
kernel_type = "rbf"  # Plus lisse
# Ou augmenter n_initial_points

Bonnes Pratiques

1. Commencez par le Noyau Mixte

# Recommandation par défaut
kernel_type = "mixed"

2. Testez Plusieurs Noyaux

# Pour des problèmes critiques
kernels_to_test = ["mixed", "matern", "rbf"]
# Comparez les résultats

3. Adaptez selon les Variables

# Analysez vos variables
if mostly_discrete:
    kernel_type = "categorical"
elif mostly_continuous:
    kernel_type = "matern"
else:
    kernel_type = "mixed"

4. Surveillez les Logs

import logging
logging.basicConfig(level=logging.INFO)

# Les logs affichent le type de noyau utilisé
# et les informations sur les variables discrètes

Exemple Complet

#!/usr/bin/env python3
"""
Exemple complet d'optimisation avec sélection de noyau
"""

import logging
from oreni.optim.botorch_optimization import botorch_multi_objective_optimizer_kernel

# Configuration du logging
logging.basicConfig(level=logging.INFO)

# Configuration de l'optimisation
def optimize_with_kernel_selection(kernel_type="mixed"):
    """Optimisation avec sélection de noyau."""

    results = botorch_multi_objective_optimizer_kernel(
        function=Simuls.compute_cost_functions,
        decision_space=decision_space,
        uncertain_space=uncertain_space,
        function_labels=["Life_Cycle_Cost", "Life_Cycle_Assessment", "Thermal_Comfort"],
        n_initial_points=10,
        n_optimization_iterations=20,
        n_uncs=5,
        kernel_type=kernel_type,  # Sélection du noyau
        batch_size=2,
        raw_samples=512,
        num_restarts=10
    )

    return results

# Test de différents noyaux
kernels = ["mixed", "matern", "rbf", "categorical"]

for kernel in kernels:
    print(f"\n🔬 Test du noyau: {kernel}")
    try:
        results = optimize_with_kernel_selection(kernel)
        print(f"✅ Succès avec le noyau {kernel}")
    except Exception as e:
        print(f"❌ Erreur avec le noyau {kernel}: {e}")

Conclusion

Le choix du noyau dépend de la nature de vos variables et de vos objectifs :

  • mixed : Recommandé par défaut, adaptatif
  • matern : Excellent pour les variables continues
  • rbf : Robuste et lisse, bon pour la convergence
  • categorical : Spécialisé pour les variables discrètes

Testez plusieurs noyaux pour trouver celui qui convient le mieux à votre problème spécifique !