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.
Instant Search
The instant_search()
method provides immediate suggestions based on predefined heuristics.
This method is best when you need:
Quick results without extensive search
Proven configurations for common model types
from pruna_pro import OptimizationAgent
from pruna.evaluation.task import Task
from pruna.data.pruna_datamodule import PrunaDataModule
from diffusers import StableDiffusionPipeline
# Define your task with metrics and your model
model = StableDiffusionPipeline.from_pretrained("CompVis/stable-diffusion-v1-4")
task = Task(['elapsed_time'], datamodule=PrunaDataModule.from_string('LAION256'))
# Create the optimization agent with the model and your objectives
agent = OptimizationAgent(model=model, task=task)
# Find the best configuration instantly
optimized_model = agent.instant_search()
Note
Currently, OptimizationAgent.instant_search()
only supports a single efficiency objective at a time and does not take into consideration specific quality metrics.
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.