use rand::Rng;
use rand::SeedableRng;
use rand::rngs::StdRng;
pub type RegressionSample = (Vec<f32>, Vec<f32>);
pub fn make_regression_dataset(
n_samples: usize,
in_dim: usize,
out_dim: usize,
seed: u64,
) -> Vec<RegressionSample> {
if n_samples == 0 {
return Vec::new();
}
assert!(in_dim >= 1, "in_dim must be >= 1");
assert!(out_dim >= 1, "out_dim must be >= 1");
let mut rng = StdRng::seed_from_u64(seed);
let w_std = 1.0f32 / (in_dim as f32).sqrt();
let mut w_star: Vec<f32> = Vec::with_capacity(in_dim * out_dim);
for _ in 0..(in_dim * out_dim) {
w_star.push(gauss(&mut rng, 0.0f32, w_std));
}
let noise_std = 1e-2f32;
let mut out: Vec<RegressionSample> = Vec::with_capacity(n_samples);
for _ in 0..n_samples {
let mut x: Vec<f32> = Vec::with_capacity(in_dim);
for _ in 0..in_dim {
x.push(rng.gen_range(-0.5f32..0.5f32));
}
let mut y: Vec<f32> = vec![0.0f32; out_dim];
for j in 0..out_dim {
let mut acc = 0.0f32;
for i in 0..in_dim {
acc += x[i] * w_star[j * in_dim + i];
}
y[j] = acc + gauss(&mut rng, 0.0f32, noise_std);
}
out.push((x, y));
}
out
}
#[inline]
fn gauss<R: Rng>(rng: &mut R, mean: f32, std: f32) -> f32 {
let u1: f32 = rng.gen_range((1.0e-7f32)..1.0f32);
let u2: f32 = rng.gen_range(0.0f32..1.0f32);
let z0 = (-2.0f32 * u1.ln()).sqrt() * (2.0f32 * std::f32::consts::PI * u2).cos();
mean + std * z0
}