| name | parallel-grid-search-python |
| description | How to parallelize a grid search over hyperparameter combinations in Python using joblib or multiprocessing for CPU-bound tasks like DBSCAN clustering. |
Parallel Grid Search in Python
Grid Construction
import itertools
import numpy as np
min_samples_range = list(range(3, 10))
epsilon_range = list(range(4, 25, 2))
shape_weight_range = [round(0.9 + 0.1*i, 1) for i in range(11)]
all_combos = list(itertools.product(min_samples_range, epsilon_range, shape_weight_range))
Using joblib for Parallelization
from joblib import Parallel, delayed
def evaluate_params(min_samples, epsilon, shape_weight, citsci_df, expert_df):
"""Evaluate one hyperparameter combination across all images."""
return {
'min_samples': min_samples,
'epsilon': epsilon,
'shape_weight': shape_weight,
'F1': avg_f1,
'delta': avg_delta
}
results = Parallel(n_jobs=-1, verbose=10)(
delayed(evaluate_params)(ms, eps, sw, citsci_df, expert_df)
for ms, eps, sw in all_combos
)
Performance Tips
- Precompute per-image data: Group citizen science points by
file_rad once, outside the loop
- Use precomputed distance matrices: For each image's points, compute the distance matrix inside the evaluation
- Avoid passing large DataFrames: Instead, pass pre-grouped dictionaries
- n_jobs=-1: Uses all available CPU cores
citsci_grouped = {}
for file_rad, group in citsci_df.groupby('file_rad'):
citsci_grouped[file_rad] = group[['x', 'y']].values
expert_grouped = {}
for file_rad, group in expert_df.groupby('file_rad'):
expert_grouped[file_rad] = group[['x', 'y']].values
unique_images = list(expert_grouped.keys())
Memory Considerations
- With 847 combinations and many images, memory can be an issue
- Distance matrices are O(n²) per image — but citizen science annotations per image are typically small
- Consider batching if memory is tight