11//! # Dataset Generators
22//!
3+ use rand:: distr:: Distribution ;
34use rand:: distr:: Uniform ;
4- use rand:: prelude:: * ;
5- use rand_distr:: Normal ;
65
76use crate :: dataset:: Dataset ;
87
8+ /// Sample from N(mean, std) via Box-Muller transform using only rand 0.10
9+ #[ inline]
10+ fn sample_normal ( mean : f32 , std : f32 , rng : & mut impl rand:: Rng ) -> f32 {
11+ let unit = Uniform :: new ( f32:: EPSILON , 1.0f32 ) . unwrap ( ) ;
12+ let u1 = unit. sample ( rng) ;
13+ let u2 = unit. sample ( rng) ;
14+ let z = ( -2.0 * u1. ln ( ) ) . sqrt ( ) * ( 2.0 * std:: f32:: consts:: PI * u2) . cos ( ) ;
15+ mean + std * z
16+ }
17+
918/// Generate `num_centers` clusters of normally distributed points
1019pub fn make_blobs (
1120 num_samples : usize ,
1221 num_features : usize ,
1322 num_centers : usize ,
1423) -> Dataset < f32 , f32 > {
15- let center_box = Uniform :: new ( -10.0 , 10.0 ) . expect ( "Invalid uniform range" ) ;
16- let cluster_std = 1.0 ;
17- let mut centers: Vec < Vec < Normal < f32 > > > = Vec :: with_capacity ( num_centers) ;
18-
24+ let center_box = Uniform :: new ( -10.0f32 , 10.0f32 ) . expect ( "Invalid uniform range" ) ;
25+ let cluster_std = 1.0f32 ;
1926 let mut rng = rand:: rng ( ) ;
20- for _ in 0 ..num_centers {
21- centers. push (
27+
28+ // Pre-compute cluster centers (one mean per feature per cluster)
29+ let centers: Vec < Vec < f32 > > = ( 0 ..num_centers)
30+ . map ( |_| {
2231 ( 0 ..num_features)
23- . map ( |_| Normal :: new ( center_box. sample ( & mut rng) , cluster_std ) . unwrap ( ) )
24- . collect ( ) ,
25- ) ;
26- }
32+ . map ( |_| center_box. sample ( & mut rng) )
33+ . collect ( )
34+ } )
35+ . collect ( ) ;
2736
2837 let mut y: Vec < f32 > = Vec :: with_capacity ( num_samples) ;
29- let mut x: Vec < f32 > = Vec :: with_capacity ( num_samples) ;
38+ let mut x: Vec < f32 > = Vec :: with_capacity ( num_samples * num_features ) ;
3039
3140 for i in 0 ..num_samples {
3241 let label = i % num_centers;
3342 y. push ( label as f32 ) ;
3443 for j in 0 ..num_features {
35- x. push ( centers[ label] [ j] . sample ( & mut rng) ) ;
44+ x. push ( sample_normal ( centers[ label] [ j] , cluster_std , & mut rng) ) ;
3645 }
3746 }
3847
@@ -59,21 +68,20 @@ pub fn make_circles(num_samples: usize, factor: f32, noise: f32) -> Dataset<f32,
5968 let linspace_out = linspace ( 0.0 , 2.0 * std:: f32:: consts:: PI , num_samples_out) ;
6069 let linspace_in = linspace ( 0.0 , 2.0 * std:: f32:: consts:: PI , num_samples_in) ;
6170
62- let noise = Normal :: new ( 0.0 , noise) . unwrap ( ) ;
6371 let mut rng = rand:: rng ( ) ;
6472
6573 let mut x: Vec < f32 > = Vec :: with_capacity ( num_samples * 2 ) ;
6674 let mut y: Vec < f32 > = Vec :: with_capacity ( num_samples) ;
6775
6876 for v in linspace_out {
69- x. push ( v. cos ( ) + noise . sample ( & mut rng) ) ;
70- x. push ( v. sin ( ) + noise . sample ( & mut rng) ) ;
77+ x. push ( v. cos ( ) + sample_normal ( 0.0 , noise , & mut rng) ) ;
78+ x. push ( v. sin ( ) + sample_normal ( 0.0 , noise , & mut rng) ) ;
7179 y. push ( 0.0 ) ;
7280 }
7381
7482 for v in linspace_in {
75- x. push ( v. cos ( ) * factor + noise . sample ( & mut rng) ) ;
76- x. push ( v. sin ( ) * factor + noise . sample ( & mut rng) ) ;
83+ x. push ( v. cos ( ) * factor + sample_normal ( 0.0 , noise , & mut rng) ) ;
84+ x. push ( v. sin ( ) * factor + sample_normal ( 0.0 , noise , & mut rng) ) ;
7785 y. push ( 1.0 ) ;
7886 }
7987
@@ -96,21 +104,20 @@ pub fn make_moons(num_samples: usize, noise: f32) -> Dataset<f32, u32> {
96104 let linspace_out = linspace ( 0.0 , std:: f32:: consts:: PI , num_samples_out) ;
97105 let linspace_in = linspace ( 0.0 , std:: f32:: consts:: PI , num_samples_in) ;
98106
99- let noise = Normal :: new ( 0.0 , noise) . unwrap ( ) ;
100107 let mut rng = rand:: rng ( ) ;
101108
102109 let mut x: Vec < f32 > = Vec :: with_capacity ( num_samples * 2 ) ;
103110 let mut y: Vec < f32 > = Vec :: with_capacity ( num_samples) ;
104111
105112 for v in linspace_out {
106- x. push ( v. cos ( ) + noise . sample ( & mut rng) ) ;
107- x. push ( v. sin ( ) + noise . sample ( & mut rng) ) ;
113+ x. push ( v. cos ( ) + sample_normal ( 0.0 , noise , & mut rng) ) ;
114+ x. push ( v. sin ( ) + sample_normal ( 0.0 , noise , & mut rng) ) ;
108115 y. push ( 0.0 ) ;
109116 }
110117
111118 for v in linspace_in {
112- x. push ( 1.0 - v. cos ( ) + noise . sample ( & mut rng) ) ;
113- x. push ( 1.0 - v. sin ( ) + noise . sample ( & mut rng) - 0.5 ) ;
119+ x. push ( 1.0 - v. cos ( ) + sample_normal ( 0.0 , noise , & mut rng) ) ;
120+ x. push ( 1.0 - v. sin ( ) + sample_normal ( 0.0 , noise , & mut rng) - 0.5 ) ;
114121 y. push ( 1.0 ) ;
115122 }
116123
0 commit comments