| 248 | } |
| 249 | |
| 250 | pub fn randomized_search<C, F>( |
| 251 | build_classifier: F, |
| 252 | param_space: &BTreeMap<String, RandomParamDistribution>, |
| 253 | n_iter: usize, |
| 254 | seed: u64, |
| 255 | data: SearchData<'_>, |
| 256 | n_splits: usize, |
| 257 | pct_embargo: f64, |
| 258 | scoring: SearchScoring, |
| 259 | ) -> Result<SearchResult, String> |
| 260 | where |
| 261 | C: SimpleClassifier, |
| 262 | F: Fn(&ParamSet) -> C, |
| 263 | { |
| 264 | if param_space.is_empty() { |
| 265 | return Err("param_space cannot be empty".to_string()); |
| 266 | } |
| 267 | if n_iter == 0 { |
| 268 | return Err("n_iter must be > 0".to_string()); |
| 269 | } |
| 270 | |
| 271 | let mut rng = StdRng::seed_from_u64(seed); |
| 272 | let keys: Vec<String> = param_space.keys().cloned().collect(); |
| 273 | let mut params = Vec::with_capacity(n_iter); |
| 274 | for _ in 0..n_iter { |
| 275 | let mut draw = ParamSet::new(); |
| 276 | for key in &keys { |
| 277 | let dist = param_space |
| 278 | .get(key) |
| 279 | .ok_or_else(|| format!("missing distribution for key '{key}'"))?; |
| 280 | let value = sample_distribution(dist, &mut rng)?; |
| 281 | draw.insert(key.clone(), value); |
| 282 | } |
| 283 | params.push(draw); |
| 284 | } |
| 285 | |
| 286 | search_over_params(build_classifier, params, data, n_splits, pct_embargo, scoring) |
| 287 | } |
| 288 | |
| 289 | fn sample_distribution<R: Rng + ?Sized>( |
| 290 | dist: &RandomParamDistribution, |