Example 23
intermediate
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/preprocess

What 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!");105

Console Output

$ npx tsx 23-cross-validation/index.ts
Console output demonstrating K-Fold, Stratified K-Fold, and Leave-One-Out cross-validation splits