### MLUtils.jl Hello World Example Source: https://github.com/juliaml/mlutils.jl/blob/main/README.md Demonstrates a typical ML scenario using MLUtils.jl, including loading, shuffling, splitting, cross-validation, and data augmentation. The inner loop for `eachobs` is where data is materialized into mini-batches. ```julia using MLUtils # X is a matrix of floats # Y is a vector of strings X, Y = load_iris() # The iris dataset is ordered according to their labels, # which means that we should shuffle the dataset before # partitioning it into training- and test-set. Xs, Ys = shuffleobs((X, Y)) # We leave out 15 % of the data for testing cv_data, test_data = splitobs((Xs, Ys); at=0.85) # Next we partition the data using a 10-fold scheme. for (train_data, val_data) in kfolds(cv_data; k=10) # We apply a lazy transform for data augmentation train_data = mapobs(xy -> (xy[1] .+ 0.1 .* randn.(), xy[2]), train_data) for epoch = 1:10 # Iterate over the data using mini-batches of 5 observations each for (x, y) in eachobs(train_data, batchsize=5) # ... train supervised model on minibatches here end end end ``` -------------------------------- ### Get Number of Observations from Array Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Demonstrates how to get the number of observations from a basic array dataset using `numobs`. ```julia data = [1 2; 3 4; 5 6] numobs(data) ``` -------------------------------- ### Get Number of Observations from DataFrame Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Demonstrates how to get the number of observations from a DataFrame dataset using `numobs`. ```julia using DataFrames data = DataFrame(x = 1:4, y = ["a", "b", "c", "d"]) numobs(data) ``` -------------------------------- ### joinobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Concatenates multiple data containers into a single one. This operation is useful for combining datasets, for example, during data loading or augmentation. ```APIDOC ### joinobs — Concatenate data containers ```julia using MLUtils data1 = 1:50 data2 = 51:100 joined = joinobs(data1, data2) @assert numobs(joined) == 100 @assert getobs(joined, 75) == 75 # Concatenate labeled datasets X1, Y1 = rand(4, 60), fill("cat", 60) X2, Y2 = rand(4, 40), fill("dog", 40) combined = joinobs((X1, Y1), (X2, Y2)) @assert numobs(combined) == 100 ``` ``` -------------------------------- ### Get Number of Observations from Named Tuple Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Demonstrates how to get the number of observations from a named tuple dataset using `numobs`. ```julia data = (x = ones(2, 3), y = [1, 2, 3]) numobs(data) ``` -------------------------------- ### Count and locate elements by value with group_counts/group_indices Source: https://context7.com/juliaml/mlutils.jl/llms.txt Use `group_counts` to count occurrences of unique values in a collection and `group_indices` to get the indices for each unique value. Useful for stratified sampling. ```julia using MLUtils Y = [:cat, :dog, :dog, :cat, :cat, :bird] # Count occurrences of each unique value group_counts(Y) # Dict(:cat => 3, :dog => 2, :bird => 1) # Get indices for each unique value group_indices(Y) # Dict(:cat => [1,4,5], :dog => [2,3], :bird => [6]) # Common use: stratified sampling X = rand(4, 6) idxs = group_indices(Y) train_idxs = vcat([sample(v, ceil(Int, 0.7*length(v)); replace=false) for v in values(idxs)]...) ``` -------------------------------- ### Create a custom dataset with ObsView Source: https://context7.com/juliaml/mlutils.jl/llms.txt Demonstrates how to create a custom dataset type and use ObsView for efficient, non-copying views of data. Useful for large datasets where copying is undesirable. ```julia struct MyDS; data::Matrix{Float64}; end MLUtils.numobs(d::MyDS) = size(d.data, 2) MLUtils.getobs(d::MyDS, i) = d.data[:, i] ds = MyDS(rand(4, 150)) ov = ObsView(ds, 1:100) @assert numobs(ov) == 100 obs = getobs(ov, 1:10) # fetches from the original ds ``` -------------------------------- ### Handle tuples with obsview Source: https://context7.com/juliaml/mlutils.jl/llms.txt Illustrates how `obsview` can be applied to tuples, processing each element of the tuple individually. ```julia subset = obsview((X, rand(150)), 51:100) @assert numobs(subset) == 50 @assert typeof(subset) <: Tuple ``` -------------------------------- ### Implement Custom Dataset Indexing Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to implement the `Base.getindex` function for a custom dataset type to enable observation access with `getobs`. ```julia function Base.getindex(d::DummyDataset, i::Int) 1 <= i <= d.length || throw(ArgumentError("Index out of bounds")) return 10*i end ``` -------------------------------- ### group_counts / group_indices Source: https://context7.com/juliaml/mlutils.jl/llms.txt Counts occurrences of each unique value or gets the indices for each unique value in a collection. Useful for stratified sampling. ```APIDOC ## `group_counts` / `group_indices` — Count and locate elements by value ### Description Counts occurrences of each unique value or gets the indices for each unique value in a collection. Useful for stratified sampling. ### Usage ```julia using MLUtils Y = [:cat, :dog, :dog, :cat, :cat, :bird] # Count occurrences of each unique value group_counts(Y) # Dict(:cat => 3, :dog => 2, :bird => 1) # Get indices for each unique value group_indices(Y) # Dict(:cat => [1,4,5], :dog => [2,3], :bird => [6]) ``` ### Example: Stratified Sampling ```julia idxs = group_indices(Y) train_idxs = vcat([sample(v, ceil(Int, 0.7*length(v)); replace=false) for v in values(idxs)]...) ``` ``` -------------------------------- ### Create Observation View from Array Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Demonstrates creating an observation view from an array using `obsview` to select specific observations without copying data. ```julia obsview([1 2 3; 4 5 6], 1:2) ``` -------------------------------- ### Batching, Iteration, and Views Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/api.md Utilities for batching data, iterating over observations, and creating views of the data. ```APIDOC ## batch ### Description Creates batches of observations from a dataset. ### Method `batch(data, batch_size)` ### Parameters - **data**: The dataset to batch. - **batch_size**: The desired size of each batch. ## batch_sequence ### Description Batches observations into sequences. ### Method `batch_sequence(data, batch_size)` ### Parameters - **data**: The dataset to batch. - **batch_size**: The desired size of each sequence batch. ## batchsize ### Description Returns the batch size of a batched dataset. ### Method `batchsize(batched_data)` ### Parameters - **batched_data**: The batched dataset. ## batchseq ### Description Creates batches of sequences from a dataset. ### Method `batchseq(data, batch_size)` ### Parameters - **data**: The dataset to batch. - **batch_size**: The desired size of each sequence batch. ## BatchView ### Description A view that provides access to batches of observations. ### Constructor `BatchView(data, batch_size)` ### Parameters - **data**: The underlying dataset. - **batch_size**: The size of each batch. ## eachobs ### Description Iterates over each observation in a dataset. ### Method `eachobs(data)` ### Parameters - **data**: The dataset to iterate over. ## DataLoader ### Description A utility for loading data in batches. ### Constructor `DataLoader(data, batch_size)` ### Parameters - **data**: The dataset to load. - **batch_size**: The size of each batch. ## obsview ### Description Creates a view of specific observations in a dataset. ### Method `obsview(data, indices)` ### Parameters - **data**: The dataset to create a view from. - **indices**: The indices of the observations to include in the view. ## ObsDim ### Description Represents the observation dimension in a dataset. ## ObsView ### Description A view that provides access to specific observations. ### Constructor `ObsView(data, indices)` ### Parameters - **data**: The underlying dataset. - **indices**: The indices of the observations to access. ## randobs ### Description Randomly samples observations from a dataset. ### Method `randobs(data, num_samples)` ### Parameters - **data**: The dataset to sample from. - **num_samples**: The number of random samples to retrieve. ## slidingwindow ### Description Creates a sliding window view over a dataset. ### Method `slidingwindow(data, window_size)` ### Parameters - **data**: The dataset to create a sliding window over. - **window_size**: The size of the sliding window. ``` -------------------------------- ### Implementing MLUtils.jl Dataset Interface Source: https://context7.com/juliaml/mlutils.jl/llms.txt Implement `numobs` and `getobs` for custom data types to make them compatible with MLUtils.jl utilities. The `getobs!` function can be used for in-place observation retrieval for memory efficiency. ```julia using MLUtils # Arrays work out of the box X = rand(4, 100) # 100 observations, 4 features each @assert numobs(X) == 100 @assert size(getobs(X, 1)) == (4,) # single observation @assert size(getobs(X, 1:10)) == (4, 10) # batch of 10 # Tuples and NamedTuples are supported natively data = (X=rand(4, 100), Y=rand(100)) @assert numobs(data) == 100 obs = getobs(data, 1:5) # returns (X=4×5 Matrix, Y=5-element Vector) # Implement the interface for a custom type struct MyDataset features::Matrix{Float32} labels::Vector{Int} end MLUtils.numobs(d::MyDataset) = size(d.features, 2) MLUtils.getobs(d::MyDataset, i) = (d.features[:, i], d.labels[i]) ds = MyDataset(rand(Float32, 8, 200), rand(1:3, 200)) @assert numobs(ds) == 200 x, y = getobs(ds, 42) # returns (8-element Vector{Float32}, Int) # In-place version for memory efficiency buf = getobs(X, 1) getobs!(buf, X, 5) # writes observation 5 into buf without allocation ``` -------------------------------- ### Partitioning Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/api.md Functions for partitioning datasets into training, validation, and testing sets. ```APIDOC ## leavepout ### Description Partitions a dataset for leave-p-out cross-validation. ### Method `leavepout(data, p)` ### Parameters - **data**: The dataset to partition. - **p**: The number of observations to leave out for testing. ## kfolds ### Description Partitions a dataset into k folds for cross-validation. ### Method `kfolds(data, k)` ### Parameters - **data**: The dataset to partition. - **k**: The number of folds. ## splitobs ### Description Splits a dataset into training and testing sets. ### Method `splitobs(data, ratios)` ### Parameters - **data**: The dataset to split. - **ratios**: The ratios for splitting the data. ``` -------------------------------- ### Array Constructors (like) Source: https://context7.com/juliaml/mlutils.jl/llms.txt Creates new arrays with the same backend and element type as a reference array, with optional custom shape. ```APIDOC ### Array constructors: `zeros_like`, `ones_like`, `fill_like`, `rand_like`, `randn_like`, `trues_like`, `falses_like` ### Description These create new arrays with the same backend (CPU/GPU) and element type as a reference array `x`, with optional custom shape and type. ### Usage ```julia using MLUtils x = rand(Float32, 3, 4) zeros_like(x) ones_like(x, (5, 5)) fill_like(x, 3.14f0) rand_like(x, Float64, (2, 2)) randn_like(x, (2, 2)) trues_like(x) falses_like(x, (2, 3)) ``` ### Parameters - `x`: The reference array. - `dims`: Optional custom shape for the new array. - `T`: Optional element type for the new array. - `val`: The value to fill the array with (for `fill_like`). ``` -------------------------------- ### Generate synthetic datasets with make_moons, make_spiral, make_sin, make_poly Source: https://context7.com/juliaml/mlutils.jl/llms.txt Provides functions to generate synthetic datasets for classification and regression tasks. `make_moons` and `make_spiral` are for binary classification, while `make_sin` and `make_poly` are for regression. ```julia using MLUtils # Two interleaving half-circles (binary classification) X, Y = make_moons(200; noise=0.1) @assert size(X) == (2, 200) @assert unique(Y) == [1, 2] # Two-class spiral (binary classification) X, Y = make_spiral(100; noise=0.05) @assert size(X) == (2, 200) # 2*n points @assert unique(Y) == [0, 1] # Noisy sine wave (regression) x, y = make_sin(50, 0, 2π; noise=0.2) @assert length(x) == 50 # Noisy polynomial (regression) x_vals = range(-2, 2, length=100) x, y = make_poly([1.0, 0.0, -1.0], x_vals; noise=0.05) # noisy x² - 1 @assert length(y) == 100 ``` -------------------------------- ### slidingwindow Source: https://context7.com/juliaml/mlutils.jl/llms.txt Creates a lazy rolling-window view over sequential data, supporting custom window sizes and strides. ```APIDOC ## `slidingwindow` — Lazy rolling-window view over sequential data ### Description Creates a lazy rolling-window view over sequential data, supporting custom window sizes and strides. Works with vectors and matrices. ### Usage ```julia using MLUtils # Time series: 20 steps, windows of size 5 ts = collect(11:30) sw = slidingwindow(ts; size=5) # length(sw) == 16 # stride=3: non-overlapping windows sw2 = slidingwindow(ts; size=5, stride=3) # for w in sw2; println(w); end # 11:15, 14:18, 17:21, 20:24, 23:27 # Works with matrices (observations along last dim by default) X = rand(4, 100) sw3 = slidingwindow(X; size=10, stride=5) # size(getobs(sw3, 1)) == (4, 10) ``` ``` -------------------------------- ### Batching and Padding Sequences Source: https://context7.com/juliaml/mlutils.jl/llms.txt Handles variable-length sequences by either padding them into batches or packing them into a single array. ```APIDOC ## `batchseq` / `batch_sequence` — Pad and batch variable-length sequences ### Description Handles variable-length sequences by either padding them into batches or packing them into a single array. ### Usage ```julia using MLUtils seqs = [[1, 2, 3], [4, 5]] result = batchseq(seqs, 0) seqs2 = (ones(2, 3), fill(2.0, (2, 5))) arr = batch_sequence(seqs2; pad=-1.0) ``` ### Parameters - `seqs`: A vector or tuple of sequences. - `pad`: The value to use for padding shorter sequences. - `pad`: The value to use for padding shorter sequences. ``` -------------------------------- ### Core Dataset Interface (`numobs`, `getobs`, `getobs!`) Source: https://context7.com/juliaml/mlutils.jl/llms.txt Implement the `numobs` and `getobs` functions to make custom data types compatible with MLUtils.jl. `getobs!` provides an in-place version for memory efficiency. ```APIDOC ## Core Dataset Interface ### `numobs` / `getobs` / `getobs!` — Dataset protocol from MLCore.jl Any data type that implements `numobs(data)` (returns number of observations) and `getobs(data, idx)` (retrieves observations by index or index vector) is fully compatible with all MLUtils.jl utilities. The last dimension of arrays is treated as the observation dimension by default. ```julia using MLUtils # Arrays work out of the box X = rand(4, 100) # 100 observations, 4 features each @assert numobs(X) == 100 @assert size(getobs(X, 1)) == (4,) # single observation @assert size(getobs(X, 1:10)) == (4, 10) # batch of 10 # Tuples and NamedTuples are supported natively data = (X=rand(4, 100), Y=rand(100)) @assert numobs(data) == 100 obs = getobs(data, 1:5) # returns (X=4×5 Matrix, Y=5-element Vector) # Implement the interface for a custom type struct MyDataset features::Matrix{Float32} labels::Vector{Int} end MLUtils.numobs(d::MyDataset) = size(d.features, 2) MLUtils.getobs(d::MyDataset, i) = (d.features[:, i], d.labels[i]) ds = MyDataset(rand(Float32, 8, 200), rand(1:3, 200)) @assert numobs(ds) == 200 x, y = getobs(ds, 42) # returns (8-element Vector{Float32}, Int) # In-place version for memory efficiency buf = getobs(X, 1) getobs!(buf, X, 5) # writes observation 5 into buf without allocation ``` ``` -------------------------------- ### Array constructors like `zeros_like` Source: https://context7.com/juliaml/mlutils.jl/llms.txt Create new arrays with the same backend and element type as a reference array, allowing for custom shapes and types. Includes `ones_like`, `fill_like`, `rand_like`, `randn_like`, `trues_like`, and `falses_like`. ```julia using MLUtils x = rand(Float32, 3, 4) zeros_like(x) # 3×4 Matrix{Float32} filled with 0.0 ones_like(x, (5, 5)) # 5×5 Matrix{Float32} filled with 1.0 fill_like(x, 3.14f0) # 3×4 Matrix{Float32} filled with 3.14 rand_like(x, Float64, (2, 2)) # 2×2 Matrix{Float64} with uniform random values randn_like(x, (2, 2)) # 2×2 Matrix{Float32} with normal random values trues_like(x) # 3×4 BitMatrix filled with true falses_like(x, (2, 3)) # 2×3 BitMatrix filled with false # Works with GPU arrays (e.g., CUDA.jl) # using CUDA # xcuda = CUDA.rand(3, 4) # zeros_like(xcuda) # CuArray{Float32} on the same device ``` -------------------------------- ### Use Custom Dataset with MLUtils Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Demonstrates using a custom dataset type that implements `length` and `getindex` with `numobs` and `getobs`. ```julia data = DummyDataset(10) numobs(data) getobs(data, 2) ``` -------------------------------- ### Pad and batch variable-length sequences with `batchseq` Source: https://context7.com/juliaml/mlutils.jl/llms.txt Transposes N sequences into a sequence of N-element batches, padding shorter sequences. `batch_sequence` packs variable-length sequences into a single array. ```julia using MLUtils # batchseq: transpose N sequences into a sequence of N-element batches seqs = [[1, 2, 3], [4, 5]] result = batchseq(seqs, 0) # pad shorter sequences with 0 # 3-element Vector{Vector{Int64}}: [[1,4], [2,5], [3,0]] # batch_sequence: pack variable-length sequences into a single array seqs2 = (ones(2, 3), fill(2.0, (2, 5))) # two sequences, lengths 3 and 5 arr = batch_sequence(seqs2; pad=-1.0) # 2×5×2 Array{Float64,3} — shape: (features, Lmax, N) ``` -------------------------------- ### Using eachobs for Observation Iteration Source: https://context7.com/juliaml/mlutils.jl/llms.txt `eachobs` provides a convenient way to iterate over individual observations or mini-batches, acting as a shorthand for `DataLoader` with `batchsize=-1` by default. It accepts the same keyword arguments as `DataLoader`. ```julia using MLUtils X = rand(4, 100) Y = rand(1:3, 100) # Iterate single observations for x in eachobs(X) @assert size(x) == (4,) # entered 100 times end # Mini-batches of size 10 for (x, y) in eachobs((X, Y), batchsize=10) @assert size(x) == (4, 10) # entered 10 times @assert size(y) == (10,) end # Shuffle before iterating for x in eachobs(X, batchsize=16, shuffle=true) # observations served in random order each time end ``` -------------------------------- ### Array Constructors Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/api.md Functions for creating arrays with similar properties to existing arrays. ```APIDOC ## falses_like ### Description Creates a boolean array of falses with the same size and type as the input array. ### Method `falses_like(array)` ### Parameters - **array**: The array to mimic. ## fill_like ### Description Creates an array filled with a specific value, mimicking the size and type of the input array. ### Method `fill_like(array, value)` ### Parameters - **array**: The array to mimic. - **value**: The value to fill the new array with. ## ones_like ### Description Creates an array of ones with the same size and type as the input array. ### Method `ones_like(array)` ### Parameters - **array**: The array to mimic. ## rand_like ### Description Creates an array of random numbers with the same size and type as the input array. ### Method `rand_like(array)` ### Parameters - **array**: The array to mimic. ## randn_like ### Description Creates an array of standard normal random numbers with the same size and type as the input array. ### Method `randn_like(array)` ### Parameters - **array**: The array to mimic. ## trues_like ### Description Creates a boolean array of trues with the same size and type as the input array. ### Method `trues_like(array)` ### Parameters - **array**: The array to mimic. ## zeros_like ### Description Creates an array of zeros with the same size and type as the input array. ### Method `zeros_like(array)` ### Parameters - **array**: The array to mimic. ``` -------------------------------- ### Create Observation View with Specific Observation Dimension Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to use `ObsDim` with `obsview` to specify the observation dimension for multi-dimensional arrays, useful for RNNs/transformers. ```julia data = reshape([1:24;], 3, 4, 2) ov = obsview(data, ObsDim(2)) getobs(ov, 1) ``` -------------------------------- ### Implement Custom Dataset Length Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to implement the `Base.length` function for a custom dataset type to make it compatible with MLUtils.jl. ```julia struct DummyDataset length::Int end Base.length(d::DummyDataset) = d.length ``` -------------------------------- ### Create lazy rolling-window views with slidingwindow Source: https://context7.com/juliaml/mlutils.jl/llms.txt Generates a lazy rolling-window view over sequential data. Specify `size` for the window and optionally `stride` for non-overlapping windows. Works with vectors and matrices. ```julia using MLUtils # Time series: 20 steps, windows of size 5 ts = collect(11:30) sw = slidingwindow(ts; size=5) @assert length(sw) == 16 # (20 - 5 + 1) windows sw[1] # 11:15 sw[2] # 12:16 # stride=3: non-overlapping windows sw2 = slidingwindow(ts; size=5, stride=3) for w in sw2; println(w); end # 11:15, 14:18, 17:21, 20:24, 23:27 # Works with matrices (observations along last dim by default) X = rand(4, 100) sw3 = slidingwindow(X; size=10, stride=5) @assert size(getobs(sw3, 1)) == (4, 10) # each window is a 4×10 matrix ``` -------------------------------- ### Convenience Iterator `eachobs` Source: https://context7.com/juliaml/mlutils.jl/llms.txt `eachobs` is a shorthand for `DataLoader` that defaults to iterating individual observations (`batchsize=-1`). It accepts the same keyword arguments. ```APIDOC ### `eachobs` — Convenience iterator (shorthand for DataLoader) `eachobs` is a thin wrapper around `DataLoader` with `batchsize=-1` as default (iterates individual observations). Accepts the same keyword arguments. ```julia using MLUtils X = rand(4, 100) Y = rand(1:3, 100) # Iterate single observations for x in eachobs(X) @assert size(x) == (4,) # entered 100 times end # Mini-batches of size 10 for (x, y) in eachobs((X, Y), batchsize=10) @assert size(x) == (4, 10) # entered 10 times @assert size(y) == (10,) end # Shuffle before iterating for x in eachobs(X, batchsize=16, shuffle=true) # observations served in random order each time end ``` ``` -------------------------------- ### Undersample majority classes using `undersample` Source: https://context7.com/juliaml/mlutils.jl/llms.txt Balances classes by downsampling majority classes to match the minority class count. The `shuffle` argument controls whether the original order is preserved. ```julia using MLUtils X = rand(3, 6) Y = ["a", "b", "b", "b", "b", "a"] X_bal, Y_bal = undersample(X, Y) @assert size(X_bal, 2) == 4 # "b" was truncated to match "a" @assert sum(Y_bal .== "a") == 2 @assert sum(Y_bal .== "b") == 2 # Unsorted output (original order preserved when shuffle=false) X_sorted, Y_sorted = undersample(X, Y; shuffle=false) ``` -------------------------------- ### make_moons / make_spiral / make_sin / make_poly Source: https://context7.com/juliaml/mlutils.jl/llms.txt Generates synthetic datasets for classification and regression tasks. ```APIDOC ## `make_moons` / `make_spiral` / `make_sin` / `make_poly` — Synthetic dataset generators ### Description Generates synthetic datasets for various machine learning tasks, including classification and regression. ### Usage ```julia using MLUtils # Two interleaving half-circles (binary classification) X, Y = make_moons(200; noise=0.1) # size(X) == (2, 200) # unique(Y) == [1, 2] # Two-class spiral (binary classification) X, Y = make_spiral(100; noise=0.05) # size(X) == (2, 200) # unique(Y) == [0, 1] # Noisy sine wave (regression) x, y = make_sin(50, 0, 2π; noise=0.2) # length(x) == 50 # Noisy polynomial (regression) x_vals = range(-2, 2, length=100) x, y = make_poly([1.0, 0.0, -1.0], x_vals; noise=0.05) # length(y) == 100 ``` ``` -------------------------------- ### Creating Lazy Views with obsview Source: https://context7.com/juliaml/mlutils.jl/llms.txt `obsview` and `ObsView` create lazy views of datasets without copying data. For arrays, it returns a `SubArray`; for tuples, it maps over elements; for custom types, it wraps them in `ObsView`. ```julia using MLUtils X = rand(4, 150) # 150 observations # Lazy view over first 100 observations (returns SubArray for arrays) v = obsview(X, 1:100) @assert numobs(v) == 100 @assert typeof(v) <: SubArray ``` -------------------------------- ### Lazy Views with `obsview` / `ObsView` Source: https://context7.com/juliaml/mlutils.jl/llms.txt `obsview` and `ObsView` create lazy views of datasets without copying data. For arrays, it returns a `SubArray`; for tuples, it maps over elements; for custom types, it wraps in `ObsView`. ```APIDOC ### `obsview` / `ObsView` — Lazy indexed views of datasets Returns a lazy view of observations without copying data. For arrays it returns a `SubArray`; for tuples it maps over elements; for custom types it wraps in `ObsView`. ```julia using MLUtils X = rand(4, 150) # 150 observations # Lazy view over first 100 observations (returns SubArray for arrays) v = obsview(X, 1:100) @assert numobs(v) == 100 @assert typeof(v) <: SubArray ``` ``` -------------------------------- ### Using DataLoader for Mini-batch Iteration Source: https://context7.com/juliaml/mlutils.jl/llms.txt Wrap datasets with `DataLoader` to create iterators yielding mini-batches. Supports shuffling, parallel loading, partial batches, and custom collation functions. ```julia using MLUtils Xtrain = rand(Float32, 10, 1000) Ytrain = rand(1:5, 1000) # Basic usage: 32-sample batches, shuffled every epoch loader = DataLoader((data=Xtrain, label=Ytrain), batchsize=32, shuffle=true) @assert length(loader) == 32 # ceil(1000/32) for epoch in 1:5 for (x, y) in loader @assert size(x) == (10, 32) @assert size(y) == (32,) # train on (x, y)... end end # Drop last incomplete batch, load in parallel with worker threads loader = DataLoader(Xtrain, batchsize=64, partial=false, parallel=true) @assert length(loader) == 15 # floor(1000/64) # Custom collation: sequences of variable length seqs = [rand(Float32, 3, rand(5:10)) for _ in 1:100] collate_fn(batch) = batch_sequence(batch; pad=0.0f0) loader = DataLoader(seqs, batchsize=8, collate=collate_fn) batch = first(loader) # 3 × Lmax × 8 Array{Float32,3} # Access original data @assert loader.data === Xtrain ``` -------------------------------- ### Stack observations into batches using `batch` Source: https://context7.com/juliaml/mlutils.jl/llms.txt Stacks a vector of arrays into a single array along a new last dimension. Works with tuples and named tuples, and can be reversed with `unbatch`. ```julia using MLUtils # Stack a vector of arrays along a new last dimension vecs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] B = batch(vecs) # 3×3 Matrix{Int64}: # 1 4 7 # 2 5 8 # 3 6 9 # Works with tuples and named tuples nt_batch = batch([(a=[1,2], b=10), (a=[3,4], b=20)]) # (a = [1 3; 2 4], b = [10, 20]) # Reverse: split last dimension back into a vector of arrays unbatch(B) # 3-element Vector{Vector{Int64}}: [[1,2,3], [4,5,6], [7,8,9]] ``` -------------------------------- ### Datasets Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/api.md Functions for loading and generating common datasets. ```APIDOC ## Datasets.load_iris ### Description Loads the Iris dataset. ### Method `Datasets.load_iris()` ## Datasets.make_sin ### Description Generates a synthetic sine wave dataset. ### Method `Datasets.make_sin(n_samples)` ### Parameters - **n_samples**: The number of samples to generate. ## Datasets.make_spiral ### Description Generates a synthetic spiral dataset. ### Method `Datasets.make_spiral(n_samples)` ### Parameters - **n_samples**: The number of samples to generate. ## Datasets.make_poly ### Description Generates a synthetic polynomial dataset. ### Method `Datasets.make_poly(n_samples)` ### Parameters - **n_samples**: The number of samples to generate. ## Datasets.make_moons ### Description Generates a synthetic two-moons dataset. ### Method `Datasets.make_moons(n_samples)` ### Parameters - **n_samples**: The number of samples to generate. ``` -------------------------------- ### Concatenate data containers with joinobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Combines multiple data containers into a single one. Supports both simple data and tuple datasets. ```julia using MLUtils data1 = 1:50 data2 = 51:100 joined = joinobs(data1, data2) @assert numobs(joined) == 100 @assert getobs(joined, 75) == 75 ``` ```julia # Concatenate labeled datasets X1, Y1 = rand(4, 60), fill("cat", 60) X2, Y2 = rand(4, 40), fill("dog", 40) combined = joinobs((X1, Y1), (X2, Y2)) @assert numobs(combined) == 100 ``` -------------------------------- ### Data Iteration with `DataLoader` Source: https://context7.com/juliaml/mlutils.jl/llms.txt `DataLoader` wraps datasets to create iterators yielding mini-batches. It supports shuffling, parallel loading, partial batches, and custom collation. ```APIDOC ## Data Iteration ### `DataLoader` — Mini-batch iterator over datasets `DataLoader` wraps any data container and produces an iterator that yields mini-batches. Supports shuffling every epoch, parallel data loading, partial batches, and custom collation functions. ```julia using MLUtils Xtrain = rand(Float32, 10, 1000) Ytrain = rand(1:5, 1000) # Basic usage: 32-sample batches, shuffled every epoch loader = DataLoader((data=Xtrain, label=Ytrain), batchsize=32, shuffle=true) @assert length(loader) == 32 # ceil(1000/32) for epoch in 1:5 for (x, y) in loader @assert size(x) == (10, 32) @assert size(y) == (32,) # train on (x, y)... end end # Drop last incomplete batch, load in parallel with worker threads loader = DataLoader(Xtrain, batchsize=64, partial=true, parallel=true) @assert length(loader) == 16 # ceil(1000/64) # Custom collation: sequences of variable length seqs = [rand(Float32, 3, rand(5:10)) for _ in 1:100] collate_fn(batch) = batch_sequence(batch; pad=0.0f0) loader = DataLoader(seqs, batchsize=8, collate=collate_fn) batch = first(loader) # 3 × Lmax × 8 Array{Float32,3} # Access original data @assert loader.data === Xtrain ``` ``` -------------------------------- ### Group observations by label using groupobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Splits a dataset into a dictionary where keys are labels and values are data containers for observations belonging to that label. Requires a function to extract the label from an observation. ```julia using MLUtils X, Y = load_iris() dataset = (X, Y) # Split into one data container per class groups = groupobs(xy -> xy[2], dataset) # groups is a Dict: "setosa" => ..., "versicolor" => ..., "virginica" => ... @assert length(groups) == 3 @assert numobs(groups["setosa"]) == 50 ``` -------------------------------- ### Undersampling for Class Balancing Source: https://context7.com/juliaml/mlutils.jl/llms.txt Balances classes by downsampling majority classes to match the minority class count. Preserves original order when shuffle is false. ```APIDOC ## `undersample` — Balance classes by downsampling majority classes ### Description Balances classes by downsampling majority classes to match the minority class count. Preserves original order when shuffle is false. ### Usage ```julia using MLUtils X = rand(3, 6) Y = ["a", "b", "b", "b", "b", "a"] X_bal, Y_bal = undersample(X, Y) X_sorted, Y_sorted = undersample(X, Y; shuffle=false) ``` ### Parameters - `X`: Input data features. - `Y`: Input data labels. - `shuffle` (Optional): Whether to shuffle the data before undersampling. ``` -------------------------------- ### Resampling Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/api.md Functions for oversampling and undersampling datasets. ```APIDOC ## oversample ### Description Oversamples a dataset to balance class distribution. ### Method `oversample(data, target_indices)` ### Parameters - **data**: The dataset to oversample. - **target_indices**: The indices of the class to oversample. ## undersample ### Description Undersamples a dataset to balance class distribution. ### Method `undersample(data, target_indices)` ### Parameters - **data**: The dataset to undersample. - **target_indices**: The indices of the class to undersample. ``` -------------------------------- ### Access Observation from DataFrame Dataset Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to access a specific observation from a DataFrame dataset using `getobs`. ```julia using DataFrames data = DataFrame(x = 1:4, y = ["a", "b", "c", "d"]) getobs(data, 3) ``` -------------------------------- ### load_iris Source: https://context7.com/juliaml/mlutils.jl/llms.txt Loads the classic Iris classification dataset. ```APIDOC ## `load_iris` — Classic Iris classification dataset ### Description Loads the classic Iris classification dataset, commonly used for benchmarking and testing. ### Usage ```julia using MLUtils X, Y = load_iris() # size(X) == (4, 150) # length(Y) == 150 # unique(Y) == ["setosa", "versicolor", "virginica"] ``` ### Example: Shuffle and Split ```julia Xs, Ys = shuffleobs((X, Y)) train, test = splitobs((Xs, Ys); at=0.8) ``` ``` -------------------------------- ### Right Padding with Constant Value Source: https://context7.com/juliaml/mlutils.jl/llms.txt Pads arrays on the right up to a target size using a specified constant value. ```APIDOC ## `rpad_constant` — Right-pad arrays to a target size ### Description Pads arrays on the right up to a target size using a specified constant value. ### Usage ```julia using MLUtils rpad_constant([1, 2, 3], 6, -1) rpad_constant([1 2; 3 4], 4; dims=1) rpad_constant([1 2; 3 4], 4) ``` ### Parameters - `array`: The array to pad. - `target_size`: The target size for the array. - `pad_value`: The value to use for padding. - `dims`: The dimension(s) along which to pad. ``` -------------------------------- ### Access Observation from Array Dataset Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to access a specific observation from an array dataset using `getobs`. ```julia data = [1 2; 3 4; 5 6] getobs(data, 1) ``` -------------------------------- ### Oversample minority classes using `oversample` Source: https://context7.com/juliaml/mlutils.jl/llms.txt Balances classes by upsampling minority classes to match the majority class count. Can be used with tuples and accepts a `fraction` argument to control the upsampling ratio. ```julia using MLUtils X = rand(3, 6) Y = ["a", "b", "b", "b", "b", "a"] # severely imbalanced X_bal, Y_bal = oversample(X, Y) @assert size(X_bal, 2) == 8 # "a" was repeated to match "b" @assert sum(Y_bal .== "a") == 4 @assert sum(Y_bal .== "b") == 4 # Tuple form: last element is treated as the class labels X_bal2, Y_bal2 = oversample((X, Y)) # equivalent # fraction=0.5: minority class gets at least 50% of majority count X_half, Y_half = oversample(X, Y; fraction=0.5, shuffle=false) ``` -------------------------------- ### Oversampling for Class Balancing Source: https://context7.com/juliaml/mlutils.jl/llms.txt Balances classes by upsampling minority classes to match the majority class count. Supports tuple input and custom fractions. ```APIDOC ## `oversample` — Balance classes by upsampling minority classes ### Description Balances classes by upsampling minority classes to match the majority class count. Supports tuple input and custom fractions. ### Usage ```julia using MLUtils X = rand(3, 6) Y = ["a", "b", "b", "b", "b", "a"] X_bal, Y_bal = oversample(X, Y) X_bal2, Y_bal2 = oversample((X, Y)) X_half, Y_half = oversample(X, Y; fraction=0.5, shuffle=false) ``` ### Parameters - `X`: Input data features. - `Y`: Input data labels. - `fraction` (Optional): The minimum fraction of the majority class count that the minority class should reach. - `shuffle` (Optional): Whether to shuffle the data before oversampling. ``` -------------------------------- ### Train/validation/test split with splitobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Splits a dataset into disjoint subsets by fraction, count, or tuple. Supports shuffling and stratified splitting to maintain class proportions. ```julia using MLUtils X, Y = load_iris() # 70/30 split train, test = splitobs((X, Y); at=0.7) @assert numobs(train) == 105 @assert numobs(test) == 45 ``` ```julia # Three-way 60/20/20 split train, val, test = splitobs((X, Y); at=(0.6, 0.2)) @assert numobs(train) == 90 @assert numobs(val) == 30 @assert numobs(test) == 30 ``` ```julia # Shuffle before splitting train, test = splitobs((X, Y); at=0.8, shuffle=true) ``` ```julia # Stratified split — preserves class proportions train_idx, test_idx = splitobs(1:150; at=0.7, stratified=Y) # Each class contributes ~70% to train and ~30% to test ``` ```julia # Integer n for exact observation count first_100, rest = splitobs(X; at=100) @assert numobs(first_100) == 100 ``` -------------------------------- ### Access Observation from Named Tuple Dataset Source: https://github.com/juliaml/mlutils.jl/blob/main/docs/src/guide.md Shows how to access a specific observation from a named tuple dataset using `getobs`. ```julia data = (x = ones(2, 3), y = [1, 2, 3]) getobs(data, 2) ``` -------------------------------- ### Shuffle observations with shuffleobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Returns a view of the dataset with observations randomly reordered without copying the underlying data. Supports reproducible shuffling with a provided RNG. ```julia using MLUtils X, Y = load_iris() # Shuffle without copying data Xs, Ys = shuffleobs((X, Y)) @assert numobs(Xs) == 150 @assert typeof(Xs) <: SubArray # no data copy ``` ```julia # Reproducible shuffle with a seeded RNG using Random rng = MersenneTwister(42) Xs2, Ys2 = shuffleobs(rng, (X, Y)) ``` -------------------------------- ### Sample random observations or batches with randobs Source: https://context7.com/juliaml/mlutils.jl/llms.txt Randomly samples a single observation or a batch of observations from a dataset. Supports datasets that implement `numobs` and `getobs`. ```julia using MLUtils X = rand(4, 100) # Single random observation obs = randobs(X) @assert size(obs) == (4,) # Random batch of 10 observations (with replacement) batch = randobs(X, 10) @assert size(batch) == (4, 10) # Works with any dataset supporting numobs/getobs X, Y = load_iris() x, y = randobs((X, Y)) # one random labeled sample ```