04-grid-search tries every combination in a fixed grid — exhaustive, but the grid itself has to be decided in advance, and its size multiplies across hyperparameters the same way a decision tree's split search grows combinatorially (03-best-split-minimal-tree). A learning rate grid of [0.01, 0.1, 1.0] will never test 0.347, no matter how good that value might be, because it was never in the list.
The fix doesn't need a smarter search order, just a different way of generating candidates: instead of a fixed, pre-listed grid, define a distribution to draw each hyperparameter from, and sample as many random configurations as the time budget allows, rather than however many a grid happens to contain.
Implement sample_params(param_distributions, rng) to draw one random configuration, then random_search(param_distributions, n_iter, fit_and_score_fn, seed=None) to repeat that n_iter times and track the best, mirroring 04-grid-search's grid_search bookkeeping.
param_distributions values are either a (low, high) tuple (continuous — sample uniformly in that range) or a list (discrete — sample one value uniformly from it).sample_params returns one dict of hyperparameter values, one draw per key in param_distributions.random_search returns the same shape as 04-grid-search's grid_search: {"best_params", "best_score", "all_scores"}, with all_scores holding exactly n_iter (params, score) pairs.np.random.default_rng(seed) before the sampling loop — not one per iteration.seed must reproduce identical all_scores and best_params across calls.Open one at a time. Each gives away a little more than the last.
sample_params just needs to tell continuous from discrete specs apart: isinstance(spec, tuple) is the continuous case, anything else (a list) is discrete.
For continuous, rng.uniform(low, high) draws anywhere in the range. For discrete, don't reach for rng.choice — index the list with a random integer, spec[rng.integers(0, len(spec))].
random_search is structurally identical to grid_search, with one swap: instead of iterating a precomputed list of combinations, call sample_params fresh inside the loop, n_iter times, using the same rng object each time so the draws are independent, not repeated.
No results yet
Run your code to check it against the examples, or submit to run every test.