.. _convolutive-evaluating: ======================================= Evaluating Convolutional Dynamic Models ======================================= This page explains how to run inference (evaluation) on trained NeurEco Convolutional Dynamic models. .. contents:: On this page :local: :depth: 2 Understanding Convolutional Dynamic Evaluation ============================================== Convolutional Dynamic models use a sliding window to process time-series data. Unlike ODE models, they need no initialization data: the model makes its first prediction as soon as a full window of inputs is available. **Key characteristics:** - No initialization data needed - The first ``window_size - 1`` time steps cannot be predicted: the model needs a full window of past inputs before it produces an output, so a sequence of ``N`` time steps gives ``N - window_size + 1`` predictions, the first one at the ``window_size``-th time step - The model predicts every time step, whatever the ``window_stride`` used for training - Simpler evaluation workflow than ODE models .. note:: The GUI's evaluation export accounts for the window: the exported file contains ``input steps - window_size + 1`` rows and its time column starts at the time of the ``window_size``-th input step, so the leading unpredicted steps are not included. The Python ``evaluate`` method returns the same rows. Evaluating a Convolutional Dynamic Model ======================================== .. tabs:: .. tab:: GUI **Loading a Model** 1. Open your project or load a saved model 2. Switch to the **Evaluation** panel **Providing Evaluation Data** 1. Click **+** next to **Evaluation files** 2. Select your input (excitation) file 3. Optionally select an output file (for comparison/metrics) **Running Evaluation** 1. Click **Evaluate** 2. View results in the plot panel 3. Use the **Sample** slider to browse through sequences 4. Compare predictions (blue) with reference (orange) if provided If the input and reference output files do not have the same number of rows, the evaluation still runs and the status bar warns that the plots compare the available data only. **Metrics** Switch to the **Metrics** panel to see: - L2 relative error for each output - Per-sequence error breakdown - Training vs. validation vs. test performance .. tab:: Python API **Loading a Model** .. code-block:: python from NeurEco import NeurEcoDynamic as Dynamic model = Dynamic.ConvolutiveDynamic() model.load("path/to/model.ecnn") **Basic Evaluation** .. code-block:: python import numpy as np # Prepare evaluation data (time in column 0) dt = 0.01 # Must match training time step time = np.arange(0, 5, dt) eval_exc = np.column_stack([time, np.random.randn(len(time), 3)]) # time + 3 inputs # Evaluate # eval_exc has time in its first column; predictions are returned time-first. outputs = model.evaluate(eval_exc) print(f"Output shape: {outputs.shape}") **Evaluating Multiple Sequences** .. code-block:: python # Multiple sequences of different lengths (each array: time in column 0) times = [ np.arange(0, 3, dt), np.arange(0, 5, dt), np.arange(0, 2, dt), ] eval_exc_list = [ np.column_stack([times[0], np.random.randn(len(times[0]), 3)]), np.column_stack([times[1], np.random.randn(len(times[1]), 3)]), np.column_stack([times[2], np.random.randn(len(times[2]), 3)]), ] # Evaluate all sequences # Each array has time in its first column; predictions are returned time-first. output_list = model.evaluate(eval_exc_list) for i, out in enumerate(output_list): print(f"Sequence {i}: output shape {out.shape}") **Computing Error** .. code-block:: python # Compare predictions to ground truth # eval_exc has time in its first column; predictions are returned time-first. predictions = model.evaluate(eval_exc) # The first window_size - 1 steps are not predicted: align the reference first. aligned_ref = reference_outputs[model.get_window_size() - 1:] # compute_error takes outputs only, so drop the leading time column from both. error = model.compute_error(predictions[:, 1:], aligned_ref[:, 1:]) print(f"L2 relative error: {error:.6f}") .. tab:: CLI **Configuration File** .. code-block:: json { "neurecoConvolutiveDynamic_evaluate": { "ecnn_filename": "./model/convolutive_model.ecnn", "exc_filenames": ["data/test/test_exc_1.csv"], "write_model_output_to_directory": "./model", "model_output_format": "csv" } } **Running Evaluation** .. code-block:: shell neureco ConvolutiveDynamic evaluate config.json The predictions are saved to the output directory, one ``_ecnn`` file per excitation file, in the ``model_output_format`` format (``"npy"`` by default, or ``"csv"``). The directory is created if it does not exist. As in Python, the first ``window_size - 1`` time steps of each file are not predicted. Method Reference ================ .. code-block:: python predictions = model.evaluate( excitations=None, # Input array(s), time in column 0 *, time=None, # Deprecated: separate time array(s) ) **Parameters:** .. list-table:: :header-rows: 1 :widths: 20 15 65 * - Parameter - Required - Description * - ``excitations`` - Yes - Input array(s) with time in the first column. Shape ``(n_samples, 1 + n_inputs)`` or a list of such arrays. * - ``time`` - No - **Deprecated** (keyword-only). Separate time array(s); emits a ``DeprecatedParameterWarning`` and returns predictions without a leading time column. **Returns:** - Single sequence: NumPy array of shape ``(n_samples - window_size + 1, 1 + n_outputs)``, with time in the first column: one row per predicted time step, from the ``window_size``-th time step on - Multiple sequences: List of such NumPy arrays .. note:: When ``excitations`` carries the time in its first column, the returned predictions are **time-first** (time in column 0). The deprecated separate-``time`` form returns predictions **without** a leading time column. Complete Evaluation Example =========================== .. code-block:: python import numpy as np from NeurEco import NeurEcoDynamic as Dynamic # Load model model = Dynamic.ConvolutiveDynamic() model.load("my_convolutive_model.ecnn") # Get model information window_size = model.get_window_size() print(f"Window size: {window_size}") # Prepare test data (time in column 0) dt = 0.01 time = np.arange(0, 10, dt) eval_exc = np.column_stack([time, np.random.randn(len(time), 3)]) reference_outputs = np.column_stack([time, np.random.randn(len(time), 2)]) # Evaluate # eval_exc has time in its first column; predictions are returned time-first. predictions = model.evaluate(eval_exc) # Align the reference with the predictions (window drops the leading steps) aligned_ref = reference_outputs[window_size - 1:] # Compute error (compute_error takes outputs only: drop the leading time column) error = model.compute_error(predictions[:, 1:], aligned_ref[:, 1:]) print(f"L2 relative error: {error:.6f}") # Per-output analysis (column 0 is time, so outputs start at column 1) for i in range(1, predictions.shape[1]): output_error = np.sqrt(np.mean((predictions[:, i] - aligned_ref[:, i])**2)) print(f"Output {i - 1} RMSE: {output_error:.6f}") Model Information ================= .. code-block:: python # Number of inputs and outputs print(f"Inputs: {model.get_input_count()}") print(f"Outputs: {model.get_output_count()}") # Window size used during training print(f"Window size: {model.get_window_size()}") Comparison with ODE Evaluation ============================== .. list-table:: :header-rows: 1 :widths: 30 35 35 * - Aspect - Convolutional Dynamic - ODE * - Initialization - Not required - Required (explicit or steady-state) * - Start of the sequence - First ``window_size - 1`` time steps not predicted - Initial conditions * - Memory - Window history - Hidden states * - Output length - Input length minus ``window_size - 1`` steps - Matches input length .. note:: In both solutions the model's internal memory is managed automatically and is not exposed to the user. Best Practices ============== 1. **Match time step**: The evaluation time step must match the training time step 2. **Provide enough history**: The first ``window_size - 1`` time steps are not predicted, so start the input data ``window_size - 1`` time steps before the first time you need a prediction for 3. **Handle multiple sequences**: Use list format for batch evaluation of multiple sequences 4. **Validate window size**: Check that your evaluation data has enough time steps for the model's window size Next Steps ========== - :ref:`Export Dynamic models ` - :ref:`Dynamic advanced features `