This page documents training-time augmentation and batch regularization currently provided by yscv-model.
- Surface:
ImageAugmentationPipeline,ImageAugmentationOp,SupervisedDataset::augment_nhwc,MixUpConfig,CutMixConfig. - Batch/data surface:
BatchIterOptions,SamplingPolicy,SupervisedDataset::batches_with_options,SupervisedDataset::split_by_counts,SupervisedDataset::split_by_ratio,SupervisedDataset::split_by_class_ratio. - Intended tensor layout: rank-4
NHWC([batch, height, width, channels]). - Goal: deterministic, reproducible augmentation for supervised training workflows.
HorizontalFlip { probability }- Per-sample horizontal mirror with probability in
[0, 1].
- Per-sample horizontal mirror with probability in
VerticalFlip { probability }- Per-sample vertical mirror with probability in
[0, 1].
- Per-sample vertical mirror with probability in
RandomRotate90 { probability }- Rotates sample by random multiples of 90 degrees with probability in
[0, 1]. - Square samples use
{0, 90, 180, 270}degrees; non-square samples use{0, 180}to preserve shape.
- Rotates sample by random multiples of 90 degrees with probability in
BrightnessJitter { max_delta }- Adds random uniform delta in
[-max_delta, +max_delta]and clamps output to[0, 1].
- Adds random uniform delta in
ContrastJitter { max_scale_delta }- Scales contrast around per-sample mean by factor in
[1-max_scale_delta, 1+max_scale_delta].
- Scales contrast around per-sample mean by factor in
GammaJitter { max_gamma_delta }- Applies gamma correction with gamma sampled in
[1-max_gamma_delta, 1+max_gamma_delta].
- Applies gamma correction with gamma sampled in
GaussianNoise { probability, std_dev }- Adds Gaussian noise sampled with standard deviation
std_devwhen Bernoulli trial succeeds. - Output values are clamped to
[0, 1].
- Adds Gaussian noise sampled with standard deviation
BoxBlur3x3 { probability }- Applies deterministic 3x3 box blur to a sample when Bernoulli trial succeeds.
RandomResizedCrop { probability, min_scale, max_scale }- Crops a random window from the sample and resizes it back to original
H x W. - Scale range is deterministic by seed and constrained by
min_scale..=max_scale.
- Crops a random window from the sample and resizes it back to original
Cutout { probability, max_height_fraction, max_width_fraction, fill_value }- Applies random rectangular erasing with deterministic seed control.
- Rectangle size is sampled per sample, bounded by configured max height/width fractions.
ChannelNormalize { mean, std }- Per-channel normalization in HWC layout:
(x - mean[c]) / std[c].
- Per-channel normalization in HWC layout:
- Pipeline construction validates operation arguments:
- flip probabilities must be finite and in
[0, 1], - random-rotate90 probability must be finite and in
[0, 1], max_deltamust be finite and>= 0,max_scale_deltamust be finite and>= 0,max_gamma_deltamust be finite and>= 0,- gaussian-noise probability must be finite and in
[0, 1], - gaussian-noise
std_devmust be finite and>= 0, box_blur_3x3probability must be finite and in[0, 1],- random-resized-crop probability must be finite and in
[0, 1], - random-resized-crop
min_scale/max_scalemust be finite in(0, 1]withmin_scale <= max_scale, - cutout
max_height_fractionandmax_width_fractionmust be finite in(0, 1], - cutout
fill_valuemust be finite, mean/stdmust be non-empty and have identical lengths,- each
meanvalue must be finite, - each
stdvalue must be finite and> 0.
- flip probabilities must be finite and in
- Applying pipeline validates input tensor shape:
- input must be rank-4
NHWC.
- input must be rank-4
- Augmentations must preserve per-sample shape.
apply_nhwcandaugment_nhwcaccept aseed: u64.- Same seed + same input + same op list => deterministic output.
- Shuffled mini-batches are deterministic by
BatchIterOptions.shuffle_seed. - Batch-level augmentation is deterministic by
BatchIterOptions.augmentation_seed. SamplingPolicy-driven order is deterministic by policy-provided seed.
BatchIterOptions:shuffle: deterministic sample-order shuffle toggle.shuffle_seed: seed for deterministic shuffle order.sampling: optional explicit policy override (Sequential,Shuffled,BalancedByClass,Weighted).drop_last: drop trailing incomplete batch.augmentation: optionalImageAugmentationPipelineapplied to batch inputs.augmentation_seed: deterministic seed base for per-batch augmentation RNG.mixup: optionalMixUpConfigfor per-batch sample/target interpolation.mixup_seed: deterministic seed base for per-batch mixup pairing/lambda.cutmix: optionalCutMixConfigfor per-batch patch replacement interpolation.cutmix_seed: deterministic seed base for per-batch CutMix pairing/patch sampling.
MixUpConfig:probability: apply mixup for a batch with probability in[0, 1].lambda_min: lower bound for interpolation weight in[0, 0.5].
- Runtime behavior:
- when enabled, both inputs and targets are mixed using the same sample pairing and lambda,
- batch shape and tensor rank are preserved,
- same seed + same batch order => deterministic mixed outputs.
CutMixConfig:probability: apply cutmix for a batch with probability in[0, 1].min_patch_fraction: lower bound for square patch side fraction in[0, 1].max_patch_fraction: upper bound for square patch side fraction in[0, 1]and>= min_patch_fraction.
- Runtime behavior:
- cutmix expects rank-4
NHWCbatch inputs, - for each sample, a partner sample is selected and a random rectangular patch is copied from partner input,
- target rows are mixed with lambda derived from replaced patch area ratio,
- same seed + same batch order => deterministic cutmix outputs.
- cutmix expects rank-4
SamplingPolicy::Sequential- emits dataset indices in natural order (
0..len).
- emits dataset indices in natural order (
SamplingPolicy::Shuffled { seed }- deterministic seeded shuffle of full epoch order.
SamplingPolicy::BalancedByClass { seed, with_replacement }- derives per-sample weights from inverse class frequency using:
- scalar class labels from
targetsshape[N, 1], or - one-hot class labels from
targetsshape[N, C],
- scalar class labels from
- scalar class labels must be finite non-negative integers,
- one-hot rows must contain exactly one active class and values close to
0or1, with_replacement=truedrawsdataset_lenbalanced samples with replacement,with_replacement=falseproduces a deterministic class-balanced weighted order without replacement.
- derives per-sample weights from inverse class frequency using:
SamplingPolicy::Weighted { weights, seed, with_replacement }- validates
weights.len() == dataset_len, - each weight must be finite and
>= 0, - at least one weight must be
> 0, with_replacement=truesamplesdataset_lendraws from weighted distribution,with_replacement=falseproduces deterministic weighted order without replacement.
- validates
split_by_counts(train_count, validation_count, shuffle, seed):- returns
DatasetSplit { train, validation, test }, - validates
train_count + validation_count <= dataset_len.
- returns
split_by_ratio(train_ratio, validation_ratio, shuffle, seed):- expects finite ratios in
[0, 1], - requires
train_ratio + validation_ratio <= 1, - test split receives remaining samples.
- expects finite ratios in
split_by_class_ratio(train_ratio, validation_ratio, shuffle, seed):- applies split ratios independently per class label and merges class-wise partitions into final train/validation/test subsets,
- supports scalar class labels (
targetsshape[N, 1]) and one-hot class labels (targetsshape[N, C]), - keeps deterministic behavior under identical seed/configuration.
use yscv_model::{
BatchIterOptions, CutMixConfig, ImageAugmentationOp, ImageAugmentationPipeline, MixUpConfig,
SamplingPolicy, SupervisedDataset,
};
use yscv_tensor::Tensor;
let dataset = SupervisedDataset::new(
Tensor::from_vec(vec![2, 2, 2, 3], vec![0.2; 24])?,
Tensor::from_vec(vec![2, 1], vec![1.0, 0.0])?,
)?;
let pipeline = ImageAugmentationPipeline::new(vec![
ImageAugmentationOp::HorizontalFlip { probability: 0.5 },
ImageAugmentationOp::RandomRotate90 { probability: 0.3 },
ImageAugmentationOp::BrightnessJitter { max_delta: 0.1 },
ImageAugmentationOp::ContrastJitter { max_scale_delta: 0.2 },
ImageAugmentationOp::GammaJitter { max_gamma_delta: 0.25 },
ImageAugmentationOp::GaussianNoise {
probability: 0.2,
std_dev: 0.03,
},
ImageAugmentationOp::BoxBlur3x3 { probability: 0.2 },
ImageAugmentationOp::RandomResizedCrop {
probability: 0.4,
min_scale: 0.6,
max_scale: 1.0,
},
ImageAugmentationOp::Cutout {
probability: 0.3,
max_height_fraction: 0.2,
max_width_fraction: 0.2,
fill_value: 0.0,
},
ImageAugmentationOp::ChannelNormalize {
mean: vec![0.485, 0.456, 0.406],
std: vec![0.229, 0.224, 0.225],
},
])?;
let augmented = dataset.augment_nhwc(&pipeline, 12345)?;
assert_eq!(augmented.targets().shape(), dataset.targets().shape());
let split = augmented.split_by_ratio(0.7, 0.15, true, 7)?;
let mixup = MixUpConfig::new()
.with_probability(0.5)?
.with_lambda_min(0.1)?;
let cutmix = CutMixConfig::new()
.with_probability(0.3)?
.with_min_patch_fraction(0.2)?
.with_max_patch_fraction(0.5)?;
let batches = split.train.batches_with_options(
8,
BatchIterOptions {
shuffle: true,
shuffle_seed: 77,
sampling: Some(SamplingPolicy::Weighted {
weights: vec![1.0; split.train.len()],
seed: 5,
with_replacement: true,
}),
drop_last: true,
augmentation: Some(pipeline.clone()),
augmentation_seed: 777,
mixup: Some(mixup),
mixup_seed: 1777,
cutmix: Some(cutmix),
cutmix_seed: 2777,
},
)?;
for batch in batches {
assert_eq!(batch.inputs.rank(), 4);
}
# Ok::<(), Box<dyn std::error::Error>>(())In addition to training-time augmentation, yscv-model provides a Compose-based transform pipeline (analogous to torchvision.transforms) for inference and preprocessing:
Normalize { mean, std }— per-channel normalization.ScaleValues { scale }— multiply all values by a scalar (e.g.,1.0/255.0).PermuteDims { order }— reorder tensor dimensions (e.g., HWC → CHW).Resize { height, width }— nearest-neighbor resize.CenterCrop { height, width }— center crop to target size.RandomHorizontalFlip { probability }— random horizontal flip.GaussianBlur { kernel_size, sigma }— Gaussian blur.
Usage:
use yscv_model::{Transform, Compose};
let transform = Compose::new(vec![
Transform::Resize { height: 224, width: 224 },
Transform::CenterCrop { height: 224, width: 224 },
Transform::ScaleValues { scale: 1.0 / 255.0 },
Transform::Normalize {
mean: vec![0.485, 0.456, 0.406],
std: vec![0.229, 0.224, 0.225],
},
]);
let output = transform.apply(&input_tensor)?;yscv-model also provides DataLoader for production data pipelines:
- Configurable batch size and drop-last behavior.
- Samplers:
RandomSampler,SequentialSampler,WeightedSampler. - Optional prefetch for overlapping data loading with training.
- Augmentation path currently targets rank-4
NHWCtensors only. - No multi-worker dataset sharding/streaming execution yet.