Search based on a custom objective function¶
Intermediate tutorial
This walkthrough assumes you are already familiar with the core ado workflow — discovery spaces, operations, and replay. If you are new to ado, work through Beyond the basics: ado with real data first. If you haven't already, also work through Search a space with an optimizer to get familiar with ray_tune.
Often, experiments do not directly produce the value you care about. For example, an experiment might measure the run time of an application, while the meaningful metric is cost — which requires knowing the price per hour of the hardware used. Another common scenario is aggregating several measurements into a single score.
In this example we install a custom experiment that calculates a cost from the workload configurations used in the Beyond the basics: ado with real data example. When the space is explored with a random walk, both wallClockRuntime and the derived cost are measured in one pass.
We will:
- Install the
ray_tuneoperator and the custom experiment package - Inspect the custom experiment's interface
- Define a discovery space that uses both the
replayexperiment and the custom cost function - Run a random walk and inspect the measurements
Prerequisites
ado-coreinstalled (pip install ado-core)- The example package cloned from GitHub (the wheel is not published to PyPI)
Clone the repository if you have not already done so:
git clone https://github.com/ibm/ado.git
cd ado
A pre-populated sample store is also required. Follow the instructions in the random walk example to load the ml-multi-cloud dataset, then export its identifier:
export SAMPLE_STORE_IDENTIFIER=<your-samplestore-identifier>
All commands in this walkthrough are run from the repository root (ado/).
TL;DR
Once the packages are installed and SAMPLE_STORE_IDENTIFIER is set:
ado create space -f examples/ml-multi-cloud/ml_multicloud_space_with_custom.yaml --set "sampleStoreIdentifier=$SAMPLE_STORE_IDENTIFIER"
ado create operation -f examples/ml-multi-cloud/randomwalk_ml_multicloud_operation.yaml --use-latest space
ado show measurements operation --use-latest
Step 1 — Install the required packages¶
The ray_tune operator¶
The ray_tune operator is distributed as a separate package:
pip install ado-ray-tune
Confirm it is registered:
ado get operators
You should see ray_tune listed:
Available operators by type:
┌───────┬─────────────┬─────────┬─────────┐
│ INDEX │ OPERATOR │ VERSION │ TYPE │
├───────┼─────────────┼─────────┼─────────┤
│ 0 │ random_walk │ 2.0.0 │ explore │
│ 1 │ ray_tune │ 2.0.3 │ explore │
│ 2 │ rifferla │ 2.0.3 │ modify │
└───────┴─────────────┴─────────┴─────────┘
The ml-multicloud-cost custom experiment¶
The example ships a custom experiment that derives a cost from two inputs: the number of nodes in the configuration and the run time measured by the benchmark_performance experiment.
Install it from the example directory:
pip install examples/ml-multi-cloud/custom_experiment/
Confirm ado can see it:
ado get experiments --details
┌───────┬────────────────────┬─────────────────────┬─────────┬─────────────┐
│ INDEX │ ACTUATOR ID │ EXPERIMENT ID │ VERSION │ DESCRIPTION │
├───────┼────────────────────┼─────────────────────┼─────────┼─────────────┤
│ 0 │ custom_experiments │ ml-multicloud-cost │ 1.0.0 │ │
│ 1 │ mock │ test-experiment │ None │ │
│ 2 │ mock │ test-experiment-two │ None │ │
└───────┴────────────────────┴─────────────────────┴─────────┴─────────────┘
Inspect the experiment interface:
ado describe experiment ml-multicloud-cost
Identifier: custom_experiments.ml-multicloud-cost@1.0.0
Version: 1.0.0
Required Inputs:
Constitutive Properties:
─────────────────────────────────────────────────────────────────────────────────────────────────
Identifier: nodes
Domain:
Type: DISCRETE_VARIABLE_TYPE
Interval: 1
Range: [0, 1000]
─────────────────────────────────────────────────────────────────────────────────────────────────
─────────────────────────────────────────────────────────────────────────────────────────────────
Identifier: cpu_family
Domain:
Type: DISCRETE_VARIABLE_TYPE
Values: [0, 1]
─────────────────────────────────────────────────────────────────────────────────────────────────
Observed Properties:
benchmark_performance-wallClockRuntime
Outputs:
───────────────────────────────────────────────────────────────────────────────────────────────────────
ml-multicloud-cost@v1-total_cost
───────────────────────────────────────────────────────────────────────────────────────────────────────
The ml-multicloud-cost experiment takes nodes and cpu_family as constitutive properties (entity-space dimensions) and wallClockRuntime as an observed property — a measurement produced by another experiment. The single output, total_cost, is the derived metric.
Tip
The benchmark_performance-wallClockRuntime observed property identifier tells you both the source experiment (benchmark_performance) and the property name (wallClockRuntime). Both experiments must appear in the same discovery space.
Step 2 — Define a discovery space¶
The file examples/ml-multi-cloud/ml_multicloud_space_with_custom.yaml extends the base space from the random walk example with an additional ml-multicloud-cost entry:
experiments:
- experimentIdentifier: "benchmark_performance"
actuatorIdentifier: "replay"
- experimentIdentifier: "ml-multicloud-cost"
actuatorIdentifier: "custom_experiments"
experimentVersion: 1.0.0
Create the space, substituting the sample store identifier you exported earlier:
ado create space -f examples/ml-multi-cloud/ml_multicloud_space_with_custom.yaml --set "sampleStoreIdentifier=$SAMPLE_STORE_IDENTIFIER"
Success! Created space with identifier: $DISCOVERY_SPACE_IDENTIFIER
Important
If an experiment takes the output of another experiment as input, both experiments must appear in the same discovery space. Omitting benchmark_performance in the example above would cause ado create space to fail with:
SpaceInconsistencyError: MeasurementSpace does not contain an experiment measuring an observed property required by another experiment in the space
Inspect the space to confirm it contains both experiments:
ado describe space --use-latest
Step 3 — Run an operation¶
Run a random walk on the new space:
ado create operation -f examples/ml-multi-cloud/randomwalk_ml_multicloud_operation.yaml --use-latest space
This behaves identically to the random walk example, except that ado now evaluates both experiments for each visited entity. The terminal output will show additional detail related to the dependent experiment.
Step 4 — Inspect the measurements¶
Retrieve the full table of measurements:
ado show measurements operation --use-latest
┌───────────────┬──────────────┬─────────────────────────────────────────────┬─────────────────────────────────────────────┬────────────┬───────┬──────────┬───────────┬────────────────────┬──────────────┬────────────────────┬───────┐
│ request_index │ result_index │ identifier │ experiment_id │ cpu_family │ nodes │ provider │ vcpu_size │ wallClockRuntime │ status │ total_cost │ valid │
├───────────────┼──────────────┼─────────────────────────────────────────────┼─────────────────────────────────────────────┼────────────┼───────┼──────────┼───────────┼────────────────────┼──────────────┼────────────────────┼───────┤
│ 1 │ 0 │ B_f0.0-c0.0-n3 │ replay.benchmark_performance │ 0.0 │ 3 │ B │ 0.0 │ 153.51639366149902 │ ok │ not_measured │ True │
│ 1 │ 0 │ B_f0.0-c0.0-n3 │ custom_experiments.ml-multicloud-cost@1.0.0 │ 0.0 │ 3 │ B │ 0.0 │ not_measured │ not_measured │ 1.2793032805124918 │ True │
└───────────────┴──────────────┴─────────────────────────────────────────────┴─────────────────────────────────────────────┴────────────┴───────┴──────────┴───────────┴────────────────────┴──────────────┴────────────────────┴───────┘
Each entity produces two rows — one per experiment. The replay row carries wallClockRuntime; the custom_experiments row carries total_cost. Note that each row only contains values for the properties measured by its respective experiment (not_measured elsewhere).
Summary¶
| Step | What you did | ado concept |
|---|---|---|
| 1 | Installed ray_tune and the custom experiment package | Operator / custom experiment |
| 2 | Defined a space with both replay and the cost function | Discovery space / dependent experiment |
| 3 | Ran a random walk that evaluated both experiments per entity | Operation / random_walk operator |
| 4 | Retrieved measurements including the derived total_cost | ado show measurements |
Going further¶
Try extending this example:
- Use a different operator — swap
random_walkforray_tuneto search for the configuration with the lowest cost; see Search a space with an optimizer - Compose multiple derived metrics — add a second custom experiment that consumes
total_costas an observed property to compute, for example, a cost-per-throughput ratio - Change the cost formula — edit
objective_function.pyinexamples/ml-multi-cloud/custom_experiment/and bump the experiment version to keep stored measurements consistent - Inspect space-level measurements — run
ado show measurements space --use-latestto see all measurements accumulated across operations, not just the latest one
What's next¶
-
Search using an optimizer
Try the Search a space with an optimizer example to see how you can drive
ray_tuneover a space to find the best-performing configuration. -
Discovering important entity space dimensions
Use
adoto identify which entity space dimensions most influence a target metric.