Skip to main content
Version: v2509

PyTorchJob Automated Tuning Scheduler

ZenithTune provides a scheduler functionality (PyTorchJobTuningScheduler) that automatically discovers PyTorchJobs and performs hyperparameter tuning in Kubernetes environments. This feature automates job tuning on clusters using only YAML annotation configuration, without writing code.

How to Use PyTorchJobTuningScheduler

PyTorchJobTuningScheduler operates with the following workflow:

This scheduler automatically monitors newly created PyTorchJobs on the Kubernetes cluster and automatically starts hyperparameter tuning for jobs that meet specific conditions (annotations).

Annotation-Based Tuning

The key feature of PyTorchJobTuningScheduler is that hyperparameter tuning starts automatically just by adding optimization configuration to the PyTorchJob YAML annotations.

1. Starting the Scheduler

Start PyTorchJobTuningScheduler as follows:

from zenith_tune.integration.kubernetes import JobFilter, PyTorchJobTuningScheduler

# Only target jobs with zenith-tune/optimization-config annotation
job_filter = JobFilter(
annotations={"zenith-tune/optimization-config": None} # Key existence check
)

scheduler = PyTorchJobTuningScheduler(
submit_namespace="default",
job_filter=job_filter,
max_concurrent_tuning=1,
)
scheduler.run()

2. Preparing Jobs for Tuning

Once the scheduler is running, add the zenith-tune/optimization-config annotation to the PyTorchJob you want to tune:

apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
generateName: my-training-
annotations:
zenith-tune/optimization-config: |
variables:
- name: "learning_rate"
type: "float"
range: [0.001, 0.1]
log: true
target_env: "LEARNING_RATE"
- name: "batch_size"
type: "int"
range: [16, 128]
step: 16
target_env: "BATCH_SIZE"
objective:
name: "loss"
regex: "Final Loss: ([0-9]+\\.?[0-9]*)"
direction: "minimize"
n_trials: 10
spec:
pytorchReplicaSpecs:
Worker:
replicas: 1
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:latest
command:
- python
- train.py
- --learning-rate
- ${LEARNING_RATE:-0.01}
- --batch-size
- ${BATCH_SIZE:-32}

Important: The environment variable names specified in target_env (e.g., LEARNING_RATE, BATCH_SIZE) will be automatically set with optimized values for each trial during tuning execution. In the example above, we reference environment variables like ${LEARNING_RATE:-0.01} and also specify default values (0.01) when values are not set.

3. Starting Automatic Tuning

With the scheduler running, when you submit a PyTorchJob with the zenith-tune/optimization-config annotation to the cluster, tuning starts automatically.

The scheduler detects newly created jobs and automatically performs hyperparameter tuning based on the annotations.

Advanced Configuration

Job Selection with JobFilter

You can use JobFilter to narrow down tuning targets with more detailed conditions.

# Target only jobs in specific namespaces
job_filter = JobFilter(
namespace_pattern=r"^ml-.*", # Namespaces starting with "ml-"
annotations={"zenith-tune/optimization-config": None}
)

# Target only jobs with specific labels
job_filter = JobFilter(
labels={"team": "ai-research"},
annotations={"zenith-tune/optimization-config": None}
)

# Combination of multiple conditions
job_filter = JobFilter(
namespace_pattern=r"^production-.*",
labels={"environment": "production"},
annotations={"zenith-tune/optimization-config": None}
)

Adjusting Concurrent Execution Count

Adjust the concurrent execution count according to cluster resources with the max_concurrent_tuning parameter:

scheduler = PyTorchJobTuningScheduler(
submit_namespace="default",
tuning_config=tuning_config,
job_filter=job_filter,
max_concurrent_tuning=5, # Run up to 5 tuning jobs simultaneously
)

Detailed Annotation Configuration Specification

Here's the precise specification for the YAML format of the zenith-tune/optimization-config annotation.

Overall Structure

metadata:
annotations:
zenith-tune/optimization-config: |
variables:
- name: <string>
type: <string>
target_env: <string>
# type-specific fields
objective:
name: <string>
regex: <string>
direction: <string>
n_trials: <integer> # Optional

variables (Tuning Parameters)

Available fields for each variable:

FieldTypeRequiredDescription
namestringYesUnique identifier for the variable used in Optuna trials
typestringYesVariable type: float, int, or categorical
target_envstringNoEnvironment variable name to set in Worker containers (uses uppercase version of name if not specified)

Type-Specific Fields

For Float type:

FieldTypeRequiredDescription
range[float, float]YesMinimum and maximum values [low, high]
logbooleanNoUse logarithmic scale (default: false)
- name: "learning_rate"
type: "float"
range: [0.0001, 0.1]
log: true
target_env: "LEARNING_RATE"

For Integer type:

FieldTypeRequiredDescription
range[int, int]YesMinimum and maximum values [low, high]
stepintNoStep size (default: 1)
- name: "batch_size"
type: "int"
range: [16, 128]
step: 16
target_env: "BATCH_SIZE"

For Categorical type:

FieldTypeRequiredDescription
choiceslistYesList of possible values
- name: "optimizer"
type: "categorical"
choices: ["adam", "sgd", "adamw"]
target_env: "OPTIMIZER_TYPE"

objective (Optimization Target)

Fields used in the objective section:

FieldTypeRequiredDescription
namestringYesHuman-readable metric name
regexstringYesRegular expression pattern to extract values
directionstringYesOptimization direction: minimize or maximize

Regular Expression Pattern Rules

  • Requires one capture group () that captures a numeric value
  • The capture group must match floating-point numbers: ([0-9]+\.?[0-9]*)
  • Special characters should be properly escaped
objective:
name: "validation_loss"
regex: "Validation Loss: ([0-9]+\\.?[0-9]*)"
direction: "minimize"

How to Stop Tuning

To stop tuning in progress, delete the original PyTorchJob:

kubectl delete pytorchjob my-training-xxxxx

When the original job is deleted, the tuning process for that job is automatically interrupted, and generation of new trial jobs stops. Trial jobs already in execution will run to completion, but new trials will not start.

Notes and Best Practices

  • Jobs that existed before the scheduler started are automatically excluded
  • Jobs generated by tuning (with the zenith-tune/created-by: PyTorchJobTuner annotation) will not be tuning targets again
  • Set max_concurrent_tuning appropriately according to cluster resource capacity
  • If the YAML format of annotations is incorrect, that job will be skipped