23
Tensors
Preprocessing
Cross-Validation Strategies
Learn different cross-validation techniques for robust model evaluation. Essential for assessing model generalization. This example uses deepbox/ndarray, deepbox/preprocess and focuses on tensor; KFold, StratifiedKFold, LeaveOneOut.
Deepbox Modules Used
deepbox/ndarraydeepbox/preprocessWhat You Will Learn
- Use deepbox/ndarray for tensor.
- Use deepbox/preprocess for KFold, StratifiedKFold, LeaveOneOut.
- Learn different cross-validation techniques for robust model evaluation. Essential for assessing model generalization.
Source Files
index.ts
1/**2 * Example 23: Cross-Validation Strategies3 *4 * Learn different cross-validation techniques for robust model evaluation.5 * Essential for assessing model generalization.6 */78import { tensor } from "deepbox/ndarray";9import { KFold, LeaveOneOut, StratifiedKFold } from "deepbox/preprocess";1011// Generate synthetic linear data12// Create training data: y = 2x + 3 + noise13const X_data: number[][] = [];14const y_data: number[] = [];1516// Populate data arrays with synthetic data17for (let i = 0; i < 50; i++) {18 const x = i / 5;19 const y = 2 * x + 3 + (Math.random() - 0.5);20 X_data.push([x]);21 y_data.push(y);22}2324// Convert data to tensors25const X = tensor(X_data);2627// Display dataset size28console.log(`Dataset: ${X.shape[0]} samples\n`);2930// 1. K-Fold Cross-Validation31// K-Fold: Split data into k equal folds32console.log("1. K-Fold Cross-Validation (k=5):");33console.log("-".repeat(50));3435// Create 5-fold cross-validator with shuffling36const kfold = new KFold({ nSplits: 5, shuffle: true, randomState: 42 });3738// Initialize fold counter39let foldNum = 1;4041// Iterate through each fold42for (const { trainIndex, testIndex } of kfold.split(X)) {43 // Note: In a real scenario, you'd use gather() to index the data44 // For this example, we'll just count the splits45 console.log(`Fold ${foldNum}: Train=${trainIndex.length}, Test=${testIndex.length}`);46 foldNum++;47}4849// Display total number of folds50console.log(`\nTotal folds: ${kfold.getNSplits()}\n`);5152// 2. Stratified K-Fold (for classification)53// Stratified K-Fold: Preserves class distribution54console.log("2. Stratified K-Fold:");55console.log("-".repeat(50));5657// Create classification data with 3 classes58const y_class = tensor([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2]);59const X_class = tensor(60 Array(12)61 .fill(0)62 .map((_, i) => [i])63);6465// Stratified split maintains class proportions in each fold66const stratified = new StratifiedKFold({67 nSplits: 3,68 shuffle: true,69 randomState: 42,70});7172// Initialize fold counter73foldNum = 1;7475// Iterate through each fold76for (const { trainIndex, testIndex } of stratified.split(X_class, y_class)) {77 console.log(`Fold ${foldNum}: Train=${trainIndex.length}, Test=${testIndex.length}`);78 foldNum++;79}8081console.log("\nStratified K-Fold preserves class distribution in each fold\n");8283// 3. Leave-One-Out Cross-Validation84// Leave-One-Out: Use n-1 samples for training, 1 for testing85console.log("3. Leave-One-Out Cross-Validation:");86console.log("-".repeat(50));8788const X_small = tensor([[1], [2], [3], [4], [5]]);8990// LOO creates n folds for n samples91const loo = new LeaveOneOut();92const looFolds = Array.from(loo.split(X_small));9394console.log(`Total folds: ${looFolds.length}`);95console.log("Each fold uses n-1 samples for training, 1 for testing");96console.log("Useful for small datasets but computationally expensive\n");9798// Summary of when to use each method99console.log("Key Insights:");100console.log("• K-Fold: Good balance between bias and variance");101console.log("• Stratified K-Fold: Maintains class distribution (classification)");102console.log("• Leave-One-Out: Maximum training data, high variance");103104console.log("\n✓ Cross-validation complete!");105Console Output
$ npx tsx 23-cross-validation/index.ts
Console output demonstrating K-Fold, Stratified K-Fold, and Leave-One-Out cross-validation splits