Efficiently Exploring Parameter Spaces with TRIM¶
The scenario
You have a complex system with many tunable parameters, like a scientific simulation or a machine learning model, which is time-consuming and expensive to run. In this example, ado's TRIM operator is used to intelligently explore the parameter space of an experiment, measuring just enough samples to build a stable and accurate predictive model. Using the TRIM operator involves:
- Defining the parameter space to explore in a
discoveryspace. - Creating an
operationthat uses TRIM to intelligently sample points, measure them, and build a model. - Observing TRIM's progress as it first characterizes the space and then iteratively refines its model. When the quality of this predictive model does not improve, TRIM stops.
Prerequisites
Get the example files and install dependencies:
git clone https://github.com/IBM/ado.git
cd ado
pip install plugins/operators/trim/
pip install -e examples/trim/custom_experiments/
Caution
All commands below assume you are running them from the top-level of the ado repository.
TL;DR
To create a discoveryspace and explore it with the TRIM operator, execute the following from the root of the ado repository:
: # Create the space to explore based on a custom experiment
ado create space -f examples/trim/example_yamls/space_pressure.yaml --new-sample-store
: # Explore it with TRIM!
ado create operation -f examples/trim/example_yamls/op_pressure.yaml \
--use-latest space
What is TRIM?¶
TRIM (Transfer Refined Iterative Modeling) is a characterization operator designed to efficiently build a surrogate model of a system. It's perfect for situations where measuring points in your parameter space is costly.
It works in two main phases:
- No-Priors Characterization: If there isn't enough existing data, TRIM starts by sampling a small, representative set of points to get a baseline understanding of the space
- Iterative Modeling: TRIM then enters a loop: it uses the data it has gathered to train a preliminary model (using
AutoGluon), uses that model's intelligence to decide which point to sample next, measures that point, and then retrains the model. It stops automatically when it determines that further sampling won't significantly improve the model's accuracy, saving you time and resources
Finally, it trains one high-quality model on all the data it has collected and saves it for you to use.
Creating a discoveryspace¶
A discoveryspace describes the parameters you want to explore (entitySpace) and how to measure them (measurementSpace). In this example, we'll use a custom Python function calculate_pressure_ideal_gas as our experiment.
First, create the discoveryspace by executing this command from the repository root:
ado create space -f examples/trim/example_yamls/space_pressure.yaml --new-sample-store
This will create a new space and a sample store to hold the measurement results. The output will be similar to:
Success! Created space with identifier: space-bfed2d-19b49a
Exploring with a TRIM Operation¶
Next, we will run an operation that uses TRIM to explore the discoveryspace. The configuration for our operation is in op_pressure.yaml:
# Copyright IBM Corporation 2025, 2026
# SPDX-License-Identifier: MIT
spaces:
- space-c8717f-3a68bf
operation:
module:
operationType: characterize
operatorName: trim
parameters:
batchSize: 1
autoGluonArgs:
fitArgs:
time_limit: 20
presets: medium
excluded_model_types:
- GBM
tabularPredictorArgs:
problem_type: regression
iterationSize: 5
outputDirectory: trim_models
stoppingCriterion:
enabled: true
meanThreshold: 0.9
stdThreshold: 0.75
noPriorsParameters:
targetOutput: pressure
targetOutput: pressure
taskId: null
taskValue: null
To run the operation, execute:
ado create operation -f examples/trim/example_yamls/op_pressure.yaml --use-latest space
What to Expect in the Terminal¶
You will see a lot of output as TRIM does its work. Let's break down the key stages:
Stage 1: No-Priors Characterization¶
Since in our example we started with an empty sample store, TRIM cannot immediately build a model. It will log this and begin the initial characterization phase.
2026-01-16 14:56:57,589 WARNING MainThread trim.utils.space_df_connector: get_df_at_least_one_measured_value: No measured properties found in the discovery space
...
2026-01-16 14:56:57,656 WARNING MainThread trim.operator : trim : Only 0 points in the source space.
Starting with no-prior characterization operation, it will sample 20 points.
It then runs a simple sampling operation (in this case, using Concatenated Latin Hypercube Sampling or clhs) to gather the initial data points. You will see output for each point being measured:
(RandomWalk pid=10734) Continuous batching: SUBMIT EXPERIMENT. Submitted experiment custom_experiments.calculate_pressure_ideal_gas for temperature.270.0-volume.5.0-mol.0.2. Request identifier: 3201d2
(RandomWalk pid=10734)
(RandomWalk pid=10734) Continuous batching: SUMMARY. Entities sampled and submitted: 1. Experiments completed: 0 Waiting on 1 active requests. There are 0 dependent experiments
(RandomWalk pid=10734) Continuous Batching: EXPERIMENT COMPLETION. Received finished notification for experiment...
Stage 2: Iterative Modeling¶
Once the initial characterization is complete, TRIM begins its main iterative loop. In each iteration, it samples a new point, trains an AutoGluon model and checks if the model's accuracy is still improving. The points to sample are chosen by leveraging the information obtained in the no-prior characterization stage.
You'll see logs indicating that a model is being trained and evaluated:
(RandomWalk pid=10736) 2026-01-16 14:57:19,256 INFO AsyncIO Thread: default trim.trim_sampler: iterator : Fitting AutoGluon TabularPredictor, iteration 5...
...
(RandomWalk pid=10736) 2026-01-16 14:57:20,723 INFO AsyncIO Thread: default trim.trim_sampler: iterator : [Batch under consideration: 5] Training metric: root_mean_squared_error;
(RandomWalk pid=10736) Best model: NeuralNetTorch; score_val: -8.49; holdout_score: -669.00
After a set number of iterations (defined by iterationSize), it will check the stopping criterion:
(RandomWalk pid=10736) 2026-01-16 14:57:48,947 INFO AsyncIO Thread: default trim.trim_sampler: iterator : Testing stopping criterion after measuring 14 points, mean_ratio={mean_ratio} and std_ratio={std_ratio}
(RandomWalk pid=10736) 2026-01-16 14:57:48,947 INFO AsyncIO Thread: default trim.trim_sampler: iterator : Stopping not triggered for i=14
Stage 3: Stopping and Finalizing¶
The iterative process continues until the model's performance stabilizes. At that point, the stopping criterion is met, and TRIM will train one final model on all the data it has gathered.
(RandomWalk pid=10736) 2026-01-16 14:58:06,441 INFO AsyncIO Thread: default trim.trim_sampler: iterator : Stopping criteria hit after measuring 22 entities.
...
(RandomWalk pid=10736) 2026-01-16 14:58:06,468 INFO AsyncIO Thread: default trim.trim_sampler: finalize_model : Finalizing the predictive model:Fitting AutoGluon TabularPredictor on full Source Space data of 42 rows.Model will be saved in: trim_models_finalized
...
(RandomWalk pid=10736) Final model root_mean_squared_error=-48.72586662062896.Saving predicted model to: trim_models_finalized.
The operation will end with a success message:
Success! Created operation with identifier operation-trim-v0.1-8b23a245 and it finished successfully.
Looking at the operation output¶
The TRIM operator saves the final trained AutoGluon model to the directory specified by the outputDirectory field in your operation parameters. The model can be then loaded as a TabularPredictor in your own code to make predictions on any unmeasured points in your parameter space.
You can also view the entities that were sampled during the entire operation. TRIM actually runs two sub-operations (one for characterization, one for iterative modeling). You can see the relationship with:
ado show related space --use-latest
This will show the discoveryspace and the sub-operations that were run. To see the entities of the space that have been measured, you can run:
ado show entities space --use-latest
This will display a table of the entities sampled and their measured pressure values.
┌───────┬──────────────────────────────────┬─────────────┬─────────────────────────────────────────────────┬─────────────┬────────┬─────┬────────────────────┐
│ INDEX │ identifier │ generatorid │ experiment_id │ temperature │ volume │ mol │ pressure │
├───────┼──────────────────────────────────┼─────────────┼─────────────────────────────────────────────────┼─────────────┼────────┼─────┼────────────────────┤
│ 0 │ temperature.270-volume.1-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 270 │ 1 │ 0.1 │ 224.49049068600002 │
│ 1 │ temperature.270-volume.2-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 270 │ 2 │ 0.1 │ 112.24524534300001 │
│ 2 │ temperature.270-volume.8-mol.0.2 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 270 │ 8 │ 0.2 │ 56.122622671500004 │
│ 3 │ temperature.272-volume.8-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 272 │ 8 │ 0.9 │ 254.4225561108 │
│ 4 │ temperature.274-volume.1-mol.0.2 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 274 │ 1 │ 0.2 │ 455.6325514664 │
│ 5 │ temperature.274-volume.4-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 274 │ 4 │ 0.9 │ 512.5866203997 │
│ 6 │ temperature.274-volume.8-mol.0.5 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 274 │ 8 │ 0.5 │ 142.38517233325 │
│ 7 │ temperature.276-volume.3-mol.0.8 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 276 │ 3 │ 0.8 │ 611.9444486848 │
│ 8 │ temperature.276-volume.7-mol.0.4 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 276 │ 7 │ 0.4 │ 131.1309532896 │
│ 9 │ temperature.278-volume.4-mol.0.6 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 278 │ 4 │ 0.6 │ 346.7130911706 │
│ 10 │ temperature.278-volume.7-mol.0.2 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 278 │ 7 │ 0.2 │ 66.04058879440001 │
│ 11 │ temperature.280-volume.2-mol.0.8 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 280 │ 2 │ 0.8 │ 931.219813216 │
│ 12 │ temperature.280-volume.6-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 280 │ 6 │ 0.9 │ 349.207429956 │
│ 13 │ temperature.280-volume.9-mol.0.3 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 280 │ 9 │ 0.3 │ 77.60165110133333 │
│ 14 │ temperature.282-volume.1-mol.0.7 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 282 │ 1 │ 0.7 │ 1641.2749207932 │
│ 15 │ temperature.282-volume.6-mol.0.5 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 282 │ 6 │ 0.5 │ 195.389871523 │
│ 16 │ temperature.282-volume.6-mol.0.7 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 282 │ 6 │ 0.7 │ 273.5458201322 │
│ 17 │ temperature.282-volume.7-mol.0.6 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 282 │ 7 │ 0.6 │ 200.97243928080002 │
│ 18 │ temperature.284-volume.3-mol.0.4 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 284 │ 3 │ 0.4 │ 314.8409844682667 │
│ 19 │ temperature.284-volume.7-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 284 │ 7 │ 0.9 │ 303.5966635944 │
│ 20 │ temperature.286-volume.4-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 286 │ 4 │ 0.1 │ 59.448407718700004 │
│ 21 │ temperature.286-volume.8-mol.0.3 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 286 │ 8 │ 0.3 │ 89.17261157805001 │
│ 22 │ temperature.286-volume.9-mol.0.7 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 286 │ 9 │ 0.7 │ 184.9506017915111 │
│ 23 │ temperature.288-volume.2-mol.0.3 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 288 │ 2 │ 0.3 │ 359.1847850976 │
│ 24 │ temperature.288-volume.7-mol.0.8 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 288 │ 7 │ 0.8 │ 273.6645981696 │
│ 25 │ temperature.290-volume.4-mol.0.7 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 290 │ 4 │ 0.7 │ 421.9589778635 │
│ 26 │ temperature.290-volume.5-mol.0.3 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 290 │ 5 │ 0.3 │ 144.67164955319998 │
│ 27 │ temperature.292-volume.8-mol.0.6 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 292 │ 8 │ 0.6 │ 182.0867313342 │
│ 28 │ temperature.292-volume.9-mol.0.4 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 292 │ 9 │ 0.4 │ 107.90324819804444 │
│ 29 │ temperature.294-volume.1-mol.0.4 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 294 │ 1 │ 0.4 │ 977.7808038768001 │
│ 30 │ temperature.294-volume.3-mol.0.5 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 294 │ 3 │ 0.5 │ 407.408668282 │
│ 31 │ temperature.294-volume.5-mol.0.5 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 294 │ 5 │ 0.5 │ 244.44520096920002 │
│ 32 │ temperature.296-volume.3-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 296 │ 3 │ 0.1 │ 82.03603116426667 │
│ 33 │ temperature.296-volume.4-mol.0.3 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 296 │ 4 │ 0.3 │ 184.5810701196 │
│ 34 │ temperature.296-volume.5-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 296 │ 5 │ 0.1 │ 49.22161869856 │
│ 35 │ temperature.296-volume.5-mol.0.7 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 296 │ 5 │ 0.7 │ 344.55133088992 │
│ 36 │ temperature.296-volume.9-mol.0.1 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 296 │ 9 │ 0.1 │ 27.345343721422225 │
│ 37 │ temperature.298-volume.2-mol.0.5 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 298 │ 2 │ 0.5 │ 619.427465041 │
│ 38 │ temperature.298-volume.5-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 298 │ 5 │ 0.9 │ 445.98777482952 │
│ 39 │ temperature.298-volume.6-mol.0.2 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 298 │ 6 │ 0.2 │ 82.59032867213334 │
│ 40 │ temperature.298-volume.9-mol.0.9 │ unk │ custom_experiments.calculate_pressure_ideal_gas │ 298 │ 9 │ 0.9 │ 247.7709860164 │
└───────┴──────────────────────────────────┴─────────────┴─────────────────────────────────────────────────┴─────────────┴────────┴─────┴────────────────────┘
Takeaways¶
- Automated Surrogate Modeling: The TRIM operator automates the process of building a surrogate model for a complex system.
- Efficient Sampling: By using an iterative, model-guided approach, TRIM avoids wasting resources on samples that provide little new information.
- Auto-Stopping: The stopping criterion ensures the process terminates once the model's quality plateaus, saving time and compute.
- Reusable Artifacts: The final output is a trained
AutoGluonmodel that can be used for further analysis and prediction.