Evaluating Convolutional Dynamic Models
Contents
Evaluating Convolutional Dynamic Models#
This page explains how to run inference (evaluation) on trained NeurEco Convolutional Dynamic models.
On this page
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 - 1time steps cannot be predicted: the model needs a full window of past inputs before it produces an output, so a sequence ofNtime steps givesN - window_size + 1predictions, the first one at thewindow_size-th time stepThe model predicts every time step, whatever the
window_strideused for trainingSimpler 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#
Loading a Model
Open your project or load a saved model
Switch to the Evaluation panel
Providing Evaluation Data
Click + next to Evaluation files
Select your input (excitation) file
Optionally select an output file (for comparison/metrics)
Running Evaluation
Click Evaluate
View results in the plot panel
Use the Sample slider to browse through sequences
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
Loading a Model
from NeurEco import NeurEcoDynamic as Dynamic
model = Dynamic.ConvolutiveDynamic()
model.load("path/to/model.ecnn")
Basic Evaluation
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
# 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
# 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}")
Configuration File
{
"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
neureco ConvolutiveDynamic evaluate config.json
The predictions are saved to the output directory, one <input name>_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#
predictions = model.evaluate(
excitations=None, # Input array(s), time in column 0
*,
time=None, # Deprecated: separate time array(s)
)
Parameters:
Parameter |
Required |
Description |
|---|---|---|
|
Yes |
Input array(s) with time in the first column. Shape |
|
No |
Deprecated (keyword-only). Separate time array(s); emits a |
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 thewindow_size-th time step onMultiple 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#
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#
# 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#
Aspect |
Convolutional Dynamic |
ODE |
|---|---|---|
Initialization |
Not required |
Required (explicit or steady-state) |
Start of the sequence |
First |
Initial conditions |
Memory |
Window history |
Hidden states |
Output length |
Input length minus |
Matches input length |
Note
In both solutions the model’s internal memory is managed automatically and is not exposed to the user.
Best Practices#
Match time step: The evaluation time step must match the training time step
Provide enough history: The first
window_size - 1time steps are not predicted, so start the input datawindow_size - 1time steps before the first time you need a prediction forHandle multiple sequences: Use list format for batch evaluation of multiple sequences
Validate window size: Check that your evaluation data has enough time steps for the model’s window size