8  Surrogate Model Visualization

This document describes the plot_surrogate() method added to the SpotOptim class, which provides visualization capabilities similar to the plotkd() function in the spotpython package.

8.1 Overview

The plot_surrogate() method creates a comprehensive 4-panel visualization of the fitted surrogate model, showing both predictions and uncertainty estimates across two selected dimensions.

8.2 Features

  • 3D Surface Plots: Visualize the surrogate’s predictions and uncertainty as 3D surfaces
  • Contour Plots: View 2D contours with overlaid evaluation points
  • Multi-dimensional Support: Visualize any two dimensions of higher-dimensional problems
  • Customizable Appearance: Control colors, resolution, transparency, and more

8.3 Usage

8.3.1 Basic Usage

import numpy as np
from spotoptim import SpotOptim

# Define objective function
def sphere(X):
    return np.sum(X**2, axis=1)

# Run optimization
optimizer = SpotOptim(fun=sphere, bounds=[(-5, 5), (-5, 5)], max_iter=20)
result = optimizer.optimize()

# Visualize the surrogate model
optimizer.plot_surrogate(i=0, j=1, show=True)

8.3.2 With Custom Parameters

optimizer.plot_surrogate(
    i=0,                          # First dimension to plot
    j=1,                          # Second dimension to plot
    var_name=['x1', 'x2'],        # Variable names for axes
    add_points=True,              # Show evaluated points
    cmap='viridis',               # Colormap
    alpha=0.7,                    # Surface transparency
    num=100,                      # Grid resolution
    contour_levels=25,            # Number of contour levels
    grid_visible=True,            # Show grid on contours
    figsize=(12, 10),             # Figure size
    show=True                     # Display immediately
)

8.3.3 Higher-Dimensional Problems

For problems with more than 2 dimensions, plot_surrogate() creates a 2D slice by fixing all other dimensions at their mean values:

# 4D optimization problem
def sphere_4d(X):
    return np.sum(X**2, axis=1)

bounds = [(-3, 3)] * 4
optimizer = SpotOptim(fun=sphere_4d, bounds=bounds, max_iter=20)
result = optimizer.optimize()

# Visualize dimensions 0 and 2 (dimensions 1 and 3 fixed at mean)
optimizer.plot_surrogate(
    i=0, j=2,
    var_name=['x0', 'x1', 'x2', 'x3']
)

# Visualize different dimension pair
optimizer.plot_surrogate(i=1, j=3, var_name=['x0', 'x1', 'x2', 'x3'])

8.4 Plot Interpretation

The visualization consists of 4 panels:

8.4.1 Top Left: Prediction Surface

  • Shows the surrogate model’s predicted function values as a 3D surface
  • Helps understand the model’s belief about the objective function landscape
  • Lower values (blue in default colormap) indicate predicted minima

8.4.2 Top Right: Prediction Uncertainty Surface

  • Shows the standard deviation of predictions as a 3D surface
  • Indicates where the model is uncertain and might benefit from more samples
  • Lower values (blue) indicate high confidence, higher values (red) indicate uncertainty

8.4.3 Bottom Left: Prediction Contour with Points

  • 2D contour plot of predictions
  • Red dots show the actual points evaluated during optimization
  • Useful for understanding the exploration-exploitation trade-off

8.4.4 Bottom Right: Uncertainty Contour with Points

  • 2D contour plot of prediction uncertainty
  • Shows how uncertainty decreases around evaluated points
  • Helps identify unexplored regions

8.5 Parameters

8.5.1 Dimension Selection

  • i (int, default=0): Index of first dimension to plot
  • j (int, default=1): Index of second dimension to plot

8.5.2 Appearance

  • var_name (list of str, optional): Names for each dimension
  • cmap (str, default=‘jet’): Matplotlib colormap name
  • alpha (float, default=0.8): Surface transparency (0=transparent, 1=opaque)
  • figsize (tuple, default=(12, 10)): Figure size in inches (width, height)

8.5.3 Grid and Resolution

  • num (int, default=100): Number of grid points per dimension
  • contour_levels (int, default=30): Number of contour levels
  • grid_visible (bool, default=True): Show grid lines on contour plots

8.5.4 Color Scaling

  • vmin (float, optional): Minimum value for color scale
  • vmax (float, optional): Maximum value for color scale

8.5.5 Display

  • show (bool, default=True): Display plot immediately
  • add_points (bool, default=True): Overlay evaluated points on contours

8.6 Examples

8.6.1 Example 1: 2D Rosenbrock Function

import numpy as np
from spotoptim import SpotOptim

def rosenbrock(X):
    X = np.atleast_2d(X)
    x, y = X[:, 0], X[:, 1]
    return (1 - x)**2 + 100 * (y - x**2)**2

optimizer = SpotOptim(
    fun=rosenbrock,
    bounds=[(-2, 2), (-2, 2)],
    max_iter=30,
    seed=42
)
result = optimizer.optimize()

# Visualize with custom colormap
optimizer.plot_surrogate(
    var_name=['x', 'y'],
    cmap='coolwarm',
    add_points=True
)

8.6.2 Example 2: Using Kriging Surrogate

import numpy as np
from spotoptim import SpotOptim, Kriging

def sphere(X):
    return np.sum(X**2, axis=1)

optimizer = SpotOptim(
    fun=sphere,
    bounds=[(-5, 5), (-5, 5)],
    surrogate=Kriging(seed=42),  # Use Kriging instead of GP
    max_iter=20
)
result = optimizer.optimize()

# The plotting works the same with any surrogate
optimizer.plot_surrogate(var_name=['x1', 'x2'])

8.6.3 Example 3: Comparing Different Dimension Pairs

# 3D problem - visualize all dimension pairs
def sphere_3d(X):
    return np.sum(X**2, axis=1)

optimizer = SpotOptim(
    fun=sphere_3d,
    bounds=[(-5, 5)] * 3,
    max_iter=25
)
result = optimizer.optimize()

# Dimensions 0 vs 1
optimizer.plot_surrogate(i=0, j=1, var_name=['x0', 'x1', 'x2'])

# Dimensions 0 vs 2
optimizer.plot_surrogate(i=0, j=2, var_name=['x0', 'x1', 'x2'])

# Dimensions 1 vs 2
optimizer.plot_surrogate(i=1, j=2, var_name=['x0', 'x1', 'x2'])

8.7 Tips and Best Practices

  1. Run Optimization First: Always call optimize() before plot_surrogate()

  2. Choose Dimensions Wisely: For high-dimensional problems, plot dimensions that you suspect are most important or interactive

  3. Adjust Resolution: Use lower num values (e.g., 50) for faster plotting, higher values (e.g., 200) for smoother surfaces

  4. Color Scales: Set vmin and vmax explicitly when comparing multiple plots to ensure consistent color scales

  5. Uncertainty Analysis: High uncertainty areas (bright colors in uncertainty plots) are good candidates for additional sampling

  6. Exploration vs Exploitation: Red dots clustered in low-prediction areas show exploitation; spread-out dots show exploration

8.8 Comparison with spotpython’s plotkd()

The plot_surrogate() method is inspired by spotpython’s plotkd() function but adapted for SpotOptim’s simplified interface:

8.8.1 Similarities

  • Same 4-panel layout (2 surfaces + 2 contours)
  • Visualizes predictions and uncertainty
  • Supports dimension selection and customization

8.8.2 Differences

  • Integration: Method of SpotOptim class (no separate function needed)
  • Simpler: Fewer parameters, more sensible defaults
  • Automatic: Uses optimizer’s bounds and data automatically
  • Type Handling: Automatically applies variable type constraints (int/float/factor)

8.9 Error Handling

The method validates inputs and provides clear error messages:

# Before optimization runs
optimizer.plot_surrogate()  # ValueError: No optimization data available

# Invalid dimension indices
optimizer.plot_surrogate(i=5, j=1)  # ValueError: i must be less than n_dim

# Same dimension twice
optimizer.plot_surrogate(i=0, j=0)  # ValueError: i and j must be different

8.10 Jupyter Notebook

Note