Optimization Agent (Pro)

The OptimizationAgent is an experimental but powerful feature in pruna_pro that automatically finds the best algorithm configuration for your model based on your specific objectives, requirements and constraints.

Optimization Strategies

The OptimizationAgent (experimental) offers two main strategies for finding the optimal configuration: instant search and probabilistic search.

Search Strategy

The probabilistic_search() method performs a custom search over the configuration space to directly optimize for your objectives defined as the Task.

This method is recommended when you need:

  • Optimal configurations (i.e. a combination of compression methods and their hyperparameters) for your specific use case

  • Balance between multiple objectives, e.g. latency and image generation quality

  • Thorough exploration of compression options to get the best result for your needs

from pruna_pro import OptimizationAgent
from pruna.evaluation.task import Task
from pruna.data.pruna_datamodule import PrunaDataModule
from diffusers import StableDiffusionPipeline

model = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")

# define custom objective combination
task = Task(['elapsed_time', 'clip_score'], datamodule=PrunaDataModule.from_string('LAION256'))

agent = OptimizationAgent(model=model, task=task)
optimized_model = agent.probabilistic_search(
    n_trials=15,              # Number of configurations to try
    n_iterations=15,          # Iterations per evaluation
    n_warmup_iterations=5,    # Warmup iterations per evaluation of efficiency metrics
)

The runtime of probabilistic_search() is largely dominated by the evaluation of different configurations. Make sure to choose a good balance between a thorough exploration and evaluation of the different configurations and a reasonable runtime.

INFO - Setting up search space for the OptimizationAgent...
INFO - Evaluating base model...
INFO - Base results: {'clip_score_y_x': 27.92333221435547, 'inference_elapsed_time_ms_@1': 47447.268310546875, 'inference_latency_ms_@1': 3163.151220703125, 'inference_throughput_batches_per_ms_@1': 0.00031614043408829305}
INFO - Starting probabilistic search...

...

INFO - Trial 5 completed with results {'clip_score_y_x': 26.025047302246094, 'inference_elapsed_time_ms_@1': 4378.603973388672, 'inference_latency_ms_@1': 291.9069315592448, 'inference_throughput_batches_per_ms_@1': 0.0034257494149193993}.
Tested configuration:
SmashConfig(
'cacher': 'periodic',
'compiler': 'stable_fast',
'distiller': 'hyper',
'hyper_agressive': True,
'periodic_cache_interval': 4,
'periodic_start_step': 4,
)
INFO - --------------------------------
INFO - Trial 4 is on the pareto front with results:
INFO - clip_score_y_x: 28.641061782836914
INFO - inference_latency_ms_@1: 3075.204524739583
INFO - Trial 2 is on the pareto front with results:
INFO - clip_score_y_x: 28.63214683532715
INFO - inference_latency_ms_@1: 3043.8365397135417
INFO - Trial 3 is on the pareto front with results:
INFO - clip_score_y_x: 26.561687469482422
INFO - inference_latency_ms_@1: 413.4533955891927
INFO - Trial 5 is on the pareto front with results:
INFO - clip_score_y_x: 26.025047302246094
INFO - inference_latency_ms_@1: 291.9069315592448
INFO - --------------------------------

The OptimizationAgent will log a variety of information during the search, including:

Base Model Results: All given target metrics evaluated on the base model - this will be our baseline configuration for comparison.

Successful Trials: The OptimizationAgent will log the results of the successful trials, including the configuration used and the objective results.

Pareto Front: The OptimizationAgent will also log the current state of the Pareto Front, which is the set of configurations that are optimal for the given objectives.

Importantly, the first trial of the search will always be the base model. If the base model disappears from the Pareto Front over the course of the search, it means that a configuration has outperformed the base model across all objectives!

When the specified number of trials is reached, the search will stop and the “knee point” of the Pareto Front, signifying the best trade-off between the objectives, will be selected as the final configuration. Additionally, all configurations on the final Pareto Front will be saved so that you can select the best one manually if needed.

Adding a Tokenizer, Processor or Calibration Data

The OptimizationAgent supports adding various components that might be needed for compression - make sure to specify as many as possible, as this will unlock more compression algorithms that can be taken into account:

from pruna_pro import OptimizationAgent
from pruna.evaluation.task import Task
from pruna.data.pruna_datamodule import PrunaDataModule
from transformers import AutoModelForCausalLM

# Set up model, task and agent
model_id = "facebook/opt-125m"
model = AutoModelForCausalLM.from_pretrained(model_id)
task = Task(['elapsed_time'], datamodule=PrunaDataModule.from_string("WikiText"))
agent = OptimizationAgent(model=model, task=task)

# Add a tokenizer if needed
agent.add_tokenizer(model_id)

# Add calibration data if needed
agent.add_data("WikiText")

# Find the best configuration instantly - now with an extended set of compatible compression algorithms
optimized_model = agent.instant_search()

Note

The data provided to the Task might differ from the data given to the OptimizationAgent in cases where you prefer to calibrate on a different dataset than the one used for evaluation.

Best Practices

Define Clear Objectives

Use appropriate metrics in your task definition that represent your optimization goals well.

Provide Sufficient Trials

For probabilistic_search(), more trials generally lead to better results and more evaluation iteration give a more accurate estimate of the model performance.