.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/03_advanced_parameter_exploration.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_03_advanced_parameter_exploration.py: Advanced: Parameter Optimization with Grid Search =================================================== This example demonstrates how to optimize kernel parameters and explore the performance of the KKF with different configurations. .. GENERATED FROM PYTHON SOURCE LINES 8-238 .. image-sg:: /auto_examples/images/sphx_glr_03_advanced_parameter_exploration_001.png :alt: Filter Performance vs Number of Features, Error Heatmap (lower is better) :srcset: /auto_examples/images/sphx_glr_03_advanced_parameter_exploration_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none ====================================================================== KKF Advanced Example: Parameter Exploration ====================================================================== Nonlinear System created: Dynamics: x[k+1] = [0.5*x[0] + sin(x[1]), 0.7*x[1] - 0.1*x[0]²] Observation: y[k] = x[0] + 0.1*x[1]² Generating synthetic data... ✓ Generated 80 timesteps Exploring different kernel configurations... Testing with 10 features: Testing RBF (0.5)... ✓ Error: 0.246964 Testing RBF (1.0)... ✓ Error: 0.197893 Testing RBF (2.0)... ✓ Error: 0.157648 Testing Matern (0.5, ν=0.5)... ✓ Error: 0.188136 Testing Matern (1.0, ν=0.5)... ✓ Error: 0.153730 Testing Matern (1.0, ν=1.5)... ✓ Error: 0.167921 Testing Matern (1.0, ν=2.5)... ✓ Error: 0.464270 Testing ExpSineSquared... /home/docs/checkouts/readthedocs.org/user_builds/kkf/envs/latest/lib/python3.11/site-packages/sklearn/gaussian_process/kernels.py:2072: RuntimeWarning: invalid value encountered in sin -2 * (np.sin(np.pi / self.periodicity * dists) / self.length_scale) ** 2 /home/docs/checkouts/readthedocs.org/user_builds/kkf/checkouts/latest/examples/03_advanced_parameter_exploration.py:51: RuntimeWarning: overflow encountered in scalar power return np.array([x[0] + 0.1 * x[1] ** 2]) /home/docs/checkouts/readthedocs.org/user_builds/kkf/envs/latest/lib/python3.11/site-packages/numpy/lib/_function_base_impl.py:2882: RuntimeWarning: invalid value encountered in subtract X -= avg[:, None] Error: SVD did not converge ✗ Failed Testing with 20 features: Testing RBF (0.5)... ✓ Error: 0.162378 Testing RBF (1.0)... ✓ Error: 0.153422 Testing RBF (2.0)... ✓ Error: 1.057204 Testing Matern (0.5, ν=0.5)... ✓ Error: 0.155281 Testing Matern (1.0, ν=0.5)... ✓ Error: 0.150585 Testing Matern (1.0, ν=1.5)... ✓ Error: 0.155577 Testing Matern (1.0, ν=2.5)... ✓ Error: 0.154337 Testing ExpSineSquared... /home/docs/checkouts/readthedocs.org/user_builds/kkf/checkouts/latest/examples/03_advanced_parameter_exploration.py:46: RuntimeWarning: overflow encountered in scalar power 0.7 * x[1] - 0.1 * x[0] ** 2 Error: SVD did not converge ✗ Failed Testing with 30 features: Testing RBF (0.5)... ✓ Error: 0.153650 Testing RBF (1.0)... ✓ Error: 0.152816 Testing RBF (2.0)... ✓ Error: 0.352561 Testing Matern (0.5, ν=0.5)... ✓ Error: 0.153690 Testing Matern (1.0, ν=0.5)... ✓ Error: 0.150283 Testing Matern (1.0, ν=1.5)... ✓ Error: 0.148903 Testing Matern (1.0, ν=2.5)... ✓ Error: 0.151051 Testing ExpSineSquared... /home/docs/checkouts/readthedocs.org/user_builds/kkf/envs/latest/lib/python3.11/site-packages/numpy/lib/_function_base_impl.py:2887: RuntimeWarning: overflow encountered in dot c = dot(X, X_T.conj()) Error: SVD did not converge ✗ Failed ====================================================================== Summary of Results (Mean Absolute Error): ====================================================================== Kernel Config 10 Features 20 Features 30 Features --------------------------------------------------------------------------- RBF (0.5) 0.246964 0.162378 0.153650 RBF (1.0) 0.197893 0.153422 0.152816 RBF (2.0) 0.157648 1.057204 0.352561 Matern (0.5, ν=0.5) 0.188136 0.155281 0.153690 Matern (1.0, ν=0.5) 0.153730 0.150585 0.150283 Matern (1.0, ν=1.5) 0.167921 0.155577 0.148903 Matern (1.0, ν=2.5) 0.464270 0.154337 0.151051 ExpSineSquared nan nan nan ====================================================================== Best Configuration: Matern (1.0, ν=1.5) with 30 features Mean Absolute Error: 0.148903 ====================================================================== Generating comparison plots... Figure saved as 'kkf_parameter_exploration.png' ====================================================================== Advanced example completed successfully! ====================================================================== | .. code-block:: Python import numpy as np import matplotlib.pyplot as plt from scipy import stats from sklearn.gaussian_process.kernels import Matern, RBF, ExpSineSquared from kkf import DynamicalSystem, KoopmanOperator, apply_koopman_kalman_filter def evaluate_filter(system, kernel, n_features, observations, initial_dist, noise_samples=50): """Evaluate filter performance for a given kernel.""" try: koop = KoopmanOperator(kernel, system) solution = apply_koopman_kalman_filter( koopman_operator=koop, observations=observations, initial_distribution=initial_dist, n_features=n_features, optimize=False, noise_samples=noise_samples, ) return solution except Exception as e: print(f" Error: {e}") return None def main(): """Run advanced optimization example.""" print("=" * 70) print("KKF Advanced Example: Parameter Exploration") print("=" * 70) # Create nonlinear system def f(x): """Nonlinear dynamics.""" return np.array([ 0.5 * x[0] + np.sin(x[1]), 0.7 * x[1] - 0.1 * x[0] ** 2 ]) def g(x): """Nonlinear observation.""" return np.array([x[0] + 0.1 * x[1] ** 2]) nx, ny = 2, 1 X_dist = stats.multivariate_normal(mean=np.zeros(nx), cov=np.eye(nx)) dyn_noise = stats.multivariate_normal(mean=np.zeros(nx), cov=0.01 * np.eye(nx)) obs_noise = stats.multivariate_normal(mean=np.zeros(ny), cov=0.02 * np.eye(ny)) system = DynamicalSystem( nx=nx, ny=ny, f=f, g=g, dist_X=X_dist, dist_dyn=dyn_noise, dist_obs=obs_noise, discrete_time=True, ) print(f"\nNonlinear System created:") print(f" Dynamics: x[k+1] = [0.5*x[0] + sin(x[1]), 0.7*x[1] - 0.1*x[0]²]") print(f" Observation: y[k] = x[0] + 0.1*x[1]²") # Generate data print(f"\nGenerating synthetic data...") n_timesteps = 80 x_true = np.zeros((n_timesteps, nx)) y_meas = np.zeros((n_timesteps, ny)) x_true[0] = np.array([1.0, 0.5]) y_meas[0] = g(x_true[0]) + obs_noise.rvs() np.random.seed(42) for t in range(1, n_timesteps): x_true[t] = f(x_true[t - 1]) + dyn_noise.rvs() y_meas[t] = g(x_true[t]) + obs_noise.rvs() print(f" ✓ Generated {n_timesteps} timesteps") # Kernel parameter exploration print(f"\nExploring different kernel configurations...") kernels_to_test = { "RBF (0.5)": RBF(length_scale=0.5), "RBF (1.0)": RBF(length_scale=1.0), "RBF (2.0)": RBF(length_scale=2.0), "Matern (0.5, ν=0.5)": Matern(length_scale=0.5, nu=0.5), "Matern (1.0, ν=0.5)": Matern(length_scale=1.0, nu=0.5), "Matern (1.0, ν=1.5)": Matern(length_scale=1.0, nu=1.5), "Matern (1.0, ν=2.5)": Matern(length_scale=1.0, nu=2.5), "ExpSineSquared": ExpSineSquared(length_scale=1.0, periodicity=1.0), } n_features_list = [10, 20, 30] results = {} for n_feat in n_features_list: results[n_feat] = {} print(f"\n Testing with {n_feat} features:") for kernel_name, kernel in kernels_to_test.items(): print(f" Testing {kernel_name}...", end=" ") solution = evaluate_filter( system, kernel, n_feat, y_meas, stats.multivariate_normal(mean=x_true[0], cov=0.1 * np.eye(nx)), noise_samples=50, ) if solution is not None: error = np.mean(np.linalg.norm(solution.x_plus - x_true, axis=1)) results[n_feat][kernel_name] = error print(f"✓ Error: {error:.6f}") else: results[n_feat][kernel_name] = np.nan print(f"✗ Failed") # Print summary print(f"\n" + "=" * 70) print("Summary of Results (Mean Absolute Error):") print("=" * 70) print(f"{'Kernel Config':<30} {'10 Features':<15} {'20 Features':<15} {'30 Features':<15}") print("-" * 75) for kernel_name in kernels_to_test.keys(): e10 = results[10].get(kernel_name, np.nan) e20 = results[20].get(kernel_name, np.nan) e30 = results[30].get(kernel_name, np.nan) print( f"{kernel_name:<30} {e10:<15.6f} {e20:<15.6f} {e30:<15.6f}" ) # Find best configuration best_config = None best_error = np.inf for n_feat, kernel_results in results.items(): for kernel_name, error in kernel_results.items(): if not np.isnan(error) and error < best_error: best_error = error best_config = (n_feat, kernel_name) print("\n" + "=" * 70) if best_config: print(f"Best Configuration: {best_config[1]} with {best_config[0]} features") print(f"Mean Absolute Error: {best_error:.6f}") print("=" * 70) # Visualization of results print(f"\nGenerating comparison plots...") fig, axes = plt.subplots(1, 2, figsize=(14, 5)) # Plot 1: Error vs number of features for different kernels for kernel_name in ["RBF (1.0)", "Matern (1.0, ν=0.5)", "Matern (1.0, ν=2.5)"]: errors = [] features = sorted(results.keys()) for n_feat in features: err = results[n_feat].get(kernel_name, np.nan) errors.append(err if not np.isnan(err) else None) # Filter out None values valid_idx = [i for i, e in enumerate(errors) if e is not None] if valid_idx: axes[0].plot( [features[i] for i in valid_idx], [errors[i] for i in valid_idx], "o-", label=kernel_name, linewidth=2, markersize=8, ) axes[0].set_xlabel("Number of Features") axes[0].set_ylabel("Mean Absolute Error") axes[0].set_title("Filter Performance vs Number of Features") axes[0].legend() axes[0].grid(True, alpha=0.3) # Plot 2: Heatmap of errors kernel_names = list(kernels_to_test.keys()) error_matrix = np.zeros((len(kernel_names), len(n_features_list))) for i, kernel_name in enumerate(kernel_names): for j, n_feat in enumerate(n_features_list): error_matrix[i, j] = results[n_feat].get(kernel_name, np.nan) im = axes[1].imshow(error_matrix, cmap="RdYlGn_r", aspect="auto") axes[1].set_xticks(np.arange(len(n_features_list))) axes[1].set_yticks(np.arange(len(kernel_names))) axes[1].set_xticklabels(n_features_list) axes[1].set_yticklabels(kernel_names, fontsize=9) axes[1].set_xlabel("Number of Features") axes[1].set_title("Error Heatmap (lower is better)") # Add text annotations for i in range(len(kernel_names)): for j in range(len(n_features_list)): text = axes[1].text( j, i, f"{error_matrix[i, j]:.4f}", ha="center", va="center", color="black" if error_matrix[i, j] < np.nanmax(error_matrix) / 2 else "white", fontsize=8, ) cbar = plt.colorbar(im, ax=axes[1]) cbar.set_label("Mean Absolute Error") plt.tight_layout() plt.savefig("kkf_parameter_exploration.png", dpi=100, bbox_inches="tight") print(" Figure saved as 'kkf_parameter_exploration.png'") plt.show() print("\n" + "=" * 70) print("Advanced example completed successfully!") print("=" * 70) if __name__ == "__main__": main() .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.078 seconds) .. _sphx_glr_download_auto_examples_03_advanced_parameter_exploration.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: 03_advanced_parameter_exploration.ipynb <03_advanced_parameter_exploration.ipynb>` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: 03_advanced_parameter_exploration.py <03_advanced_parameter_exploration.py>` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: 03_advanced_parameter_exploration.zip <03_advanced_parameter_exploration.zip>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_