VBAF.Playground.ps1
|
#Requires -Version 5.1 <# .SYNOPSIS VBAF Playground -- Start-VBAFPlayground .DESCRIPTION Interactive console menu where a student picks an algorithm, configures it, watches it train, and sees the results. No coding required -- everything driven by menu choices. WHAT YOU ARE LEARNING HERE: ============================ The Playground is a guided experiment station. It lets you explore the effect of hyperparameters without writing any code. You will see firsthand how these settings change outcomes: - Learning rate: too high = unstable, too low = slow - Epsilon decay: too fast = premature convergence - Episodes: more = better policy (usually) - Architecture: more neurons = more capacity HOW TO USE: =========== . .\VBAF.LoadAll.ps1 Start-VBAFPlayground -- full interactive menu Start-VBAFPlayground -Algorithm "DQN" -- skip to DQN directly Start-VBAFPlayground -Algorithm "QLearning" Start-VBAFPlayground -Algorithm "Enterprise" Start-VBAFPlayground -Algorithm "Supervised" .NOTES Part of VBAF (Visual AI & Reinforcement Learning Framework) Phase 7 -- interactive playground. ASCII only -- no Unicode, no emoji, no box-drawing characters. Requires: VBAF.LoadAll.ps1 #> # ============================================================================ # HELPER FUNCTIONS # ============================================================================ function Write-PlayHeader { param([string]$Title) Write-Host "" Write-Host ("=" * 65) -ForegroundColor Cyan Write-Host " $Title" -ForegroundColor Cyan Write-Host ("=" * 65) -ForegroundColor Cyan Write-Host "" } function Write-PlaySection { param([string]$Title) Write-Host "" Write-Host " -- $Title --" -ForegroundColor Yellow Write-Host "" } function Read-PlayChoice { param([string]$Prompt, [string[]]$Options) Write-Host "" for ($i = 0; $i -lt $Options.Count; $i++) { Write-Host " [$($i+1)] $($Options[$i])" -ForegroundColor White } Write-Host "" do { $input = Read-Host " $Prompt" $idx = 0 $valid = [int]::TryParse($input, [ref]$idx) -and $idx -ge 1 -and $idx -le $Options.Count if (-not $valid) { Write-Host " Please enter a number between 1 and $($Options.Count)" -ForegroundColor Red } } while (-not $valid) return $idx - 1 } function Read-PlayInt { param([string]$Prompt, [int]$Default, [int]$Min, [int]$Max) Write-Host "" do { $raw = Read-Host " $Prompt (default: $Default, range: $Min-$Max)" if ($raw -eq "") { return $Default } $val = 0 $valid = [int]::TryParse($raw, [ref]$val) -and $val -ge $Min -and $val -le $Max if (-not $valid) { Write-Host " Please enter a number between $Min and $Max" -ForegroundColor Red } } while (-not $valid) return $val } function Read-PlayDouble { param([string]$Prompt, [double]$Default) Write-Host "" $raw = Read-Host " $Prompt (default: $Default)" if ($raw -eq "") { return $Default } $val = 0.0 if ([double]::TryParse($raw, [ref]$val)) { return $val } return $Default } function Write-PlayResult { param([string]$Label, [double]$Value, [string]$Unit = "", [string]$Color = "White") Write-Host (" {0,-30} {1,10:F2}{2}" -f $Label, $Value, $Unit) -ForegroundColor $Color } # ============================================================================ # PLAYGROUND 1 -- DQN EXPERIMENT # ============================================================================ function Play-DQN { Write-PlayHeader "PLAYGROUND: DEEP Q-NETWORK (DQN)" Write-Host " Train a DQN agent and watch it learn." -ForegroundColor Gray Write-Host " Experiment with hyperparameters to see their effect." -ForegroundColor Gray Write-PlaySection "Step 1: Choose Your Environment" $envChoice = Read-PlayChoice "Pick environment" @( "CartPole -- balance a pole on a cart (classic RL benchmark)" "GridWorld -- navigate a grid to reach a goal" "RandomWalk -- simple 1D random walk" ) $envName = @("CartPole", "GridWorld", "RandomWalk")[$envChoice] Write-Host " Selected: $envName" -ForegroundColor Green Write-PlaySection "Step 2: Configure Training" $episodes = Read-PlayInt "Number of episodes" 50 10 500 $printEvery = Read-PlayInt "Print progress every N episodes" 10 1 50 Write-PlaySection "Step 3: Configure Hyperparameters" Write-Host " Press Enter to accept defaults (recommended for first run)." -ForegroundColor DarkGray $lrChoice = Read-PlayChoice "Learning rate" @( "0.001 -- default, stable" "0.01 -- faster but less stable" "0.0001 -- very slow, very stable" "Custom -- enter your own" ) $lr = switch ($lrChoice) { 0 { 0.001 } 1 { 0.01 } 2 { 0.0001 } 3 { Read-PlayDouble "Enter learning rate" 0.001 } } $epsDecayChoice = Read-PlayChoice "Epsilon decay speed" @( "0.9995 -- default, gradual decay" "0.999 -- faster decay, less exploration" "0.9999 -- slower decay, more exploration" ) $epsDecay = @(0.9995, 0.999, 0.9999)[$epsDecayChoice] $archChoice = Read-PlayChoice "Network architecture" @( "[4, 24, 24, 4] -- default, two hidden layers of 24" "[4, 64, 64, 4] -- larger, more capacity" "[4, 12, 12, 4] -- smaller, faster training" ) Write-PlaySection "Step 4: Training" Write-Host " Environment : $envName" -ForegroundColor White Write-Host " Episodes : $episodes" -ForegroundColor White Write-Host " Learning rate: $lr" -ForegroundColor White Write-Host " Epsilon decay: $epsDecay" -ForegroundColor White Write-Host "" Write-Host " Starting training..." -ForegroundColor Yellow Write-Host "" $startTime = Get-Date # Build config $config = [DQNConfig]::new() $config.LearningRate = $lr $config.EpsilonDecay = $epsDecay $config.EpsilonMin = 0.05 [int[]] $arch = switch ($archChoice) { 0 { @(4, 24, 24, 4) } 1 { @(4, 64, 64, 4) } 2 { @(4, 12, 12, 4) } } $main = [NeuralNetwork]::new($arch, $config.LearningRate) $target = [NeuralNetwork]::new($arch, $config.LearningRate) $memory = [ExperienceReplay]::new($config.MemorySize) $agent = [DQNAgent]::new($config, $main, $target, $memory) # Use built-in training $results = Invoke-DQNTraining -Episodes $episodes -PrintEvery $printEvery -FastMode $trained = $results[-1] $elapsed = (Get-Date) - $startTime Write-PlaySection "Step 5: Results" $trained.PrintStats() Write-Host "" Write-Host (" Training time: {0:F1} seconds" -f $elapsed.TotalSeconds) -ForegroundColor DarkGray Write-PlaySection "What Did You Learn?" Write-Host " - Higher learning rate: faster early progress, less stable later" -ForegroundColor DarkGray Write-Host " - Faster epsilon decay: agent commits to strategy sooner" -ForegroundColor DarkGray Write-Host " - Larger network: more capacity, slower training" -ForegroundColor DarkGray Write-Host "" Write-Host " Try again with different settings and compare the results!" -ForegroundColor Yellow Write-Host "" } # ============================================================================ # PLAYGROUND 2 -- Q-LEARNING EXPERIMENT # ============================================================================ function Play-QLearning { Write-PlayHeader "PLAYGROUND: Q-LEARNING" Write-Host " Train a Q-learning agent on the Castle problem." -ForegroundColor Gray Write-Host " Watch the Q-table grow as the agent learns." -ForegroundColor Gray Write-PlaySection "Step 1: Configure Training" $episodes = Read-PlayInt "Number of episodes" 100 10 1000 $stepsPerEp = Read-PlayInt "Steps per episode" 10 5 50 Write-PlaySection "Step 2: Configure Hyperparameters" $alphaChoice = Read-PlayChoice "Alpha (learning rate)" @( "0.1 -- default, moderate updates" "0.5 -- faster learning, less smooth" "0.01 -- very slow, very stable" ) $alpha = @(0.1, 0.5, 0.01)[$alphaChoice] $gammaChoice = Read-PlayChoice "Gamma (discount factor)" @( "0.9 -- default, values future rewards highly" "0.5 -- short-sighted, focuses on immediate reward" "0.99 -- far-sighted, plans many steps ahead" ) $gamma = @(0.9, 0.5, 0.99)[$gammaChoice] Write-PlaySection "Step 3: Training" Write-Host " Episodes : $episodes" -ForegroundColor White Write-Host " Steps/episode : $stepsPerEp" -ForegroundColor White Write-Host " Alpha : $alpha" -ForegroundColor White Write-Host " Gamma : $gamma" -ForegroundColor White Write-Host "" Write-Host " Starting training..." -ForegroundColor Yellow Write-Host "" $castleTypes = @("Gothic","FairyTale","Fortress","Palace","Wizard","Cathedral","Oriental","Ruins") $agent = [QLearningAgent]::new($castleTypes) $agent.Alpha = $alpha $agent.Gamma = $gamma $recentCastles = New-Object System.Collections.ArrayList $startTime = Get-Date for ($ep = 1; $ep -le $episodes; $ep++) { $episodeReward = 0.0 for ($step = 1; $step -le $stepsPerEp; $step++) { $context = @{ RecentTypes = $recentCastles } $state = $agent.GetState($context) $action = $agent.ChooseAction($state) $isVaried = ($recentCastles.Count -eq 0) -or ($recentCastles[-1] -ne $action) $outcome = @{ CastleType = $action IsVaried = $isVaried VisualBalance = Get-Random -Minimum 0.0 -Maximum 1.0 Engagement = Get-Random -Minimum 0.0 -Maximum 1.0 } $reward = $agent.CalculateReward($outcome) $episodeReward += $reward $recentCastles.Add($action) | Out-Null if ($recentCastles.Count -gt 5) { $recentCastles.RemoveAt(0) } $nextContext = @{ RecentTypes = $recentCastles } $nextState = $agent.GetState($nextContext) $agent.Learn($state, $action, $reward, $nextState) } $agent.EndEpisode($episodeReward) if ($ep % [Math]::Max(1, [int]($episodes / 5)) -eq 0 -or $ep -eq $episodes) { $stats = $agent.GetStats() Write-Host (" Episode {0,4} | Reward: {1,6:F2} | Epsilon: {2:F3} | Q-Table: {3} entries" -f ` $ep, $episodeReward, $stats.Epsilon, $stats.QTableSize) } } $elapsed = (Get-Date) - $startTime $final = $agent.GetStats() Write-PlaySection "Results" Write-PlayResult "Total episodes" $final.TotalEpisodes "" "White" Write-PlayResult "Average reward" $final.AverageReward "" "White" Write-PlayResult "Recent avg (10 ep)" $final.RecentAverageReward "" "Green" Write-PlayResult "Q-table entries" $final.QTableSize "" "Cyan" Write-PlayResult "Explorations" $final.ExplorationCount "" "DarkGray" Write-PlayResult "Exploitations" $final.ExploitationCount "" "DarkGray" Write-Host (" Training time: {0:F1} seconds" -f $elapsed.TotalSeconds) -ForegroundColor DarkGray Write-PlaySection "Inspect What Was Learned" Write-Host " Top states in Q-table:" -ForegroundColor Yellow $count = 0 foreach ($key in $agent.QTable.Keys) { if ($count -ge 5) { break } $parts = $key -split '\|' if ($parts.Count -ge 2) { $state = ($parts[0..($parts.Count - 2)]) -join '|' $action = $parts[-1] $qval = [double]$agent.QTable[$key] if ($qval -gt 0.5) { Write-Host (" State '{0}' -> Action '{1}' = {2:F3}" -f $state, $action, $qval) -ForegroundColor Green $count++ } } } if ($count -eq 0) { Write-Host " No strong preferences yet -- try more episodes." -ForegroundColor DarkGray } Write-PlaySection "What Did You Learn?" Write-Host " - Higher alpha: Q-values update faster but oscillate more" -ForegroundColor DarkGray Write-Host " - Lower gamma: agent ignores future rewards, focuses on now" -ForegroundColor DarkGray Write-Host " - More episodes: Q-table grows, epsilon decays, agent improves" -ForegroundColor DarkGray Write-Host "" } # ============================================================================ # PLAYGROUND 3 -- ENTERPRISE EXPERIMENT # ============================================================================ function Play-Enterprise { Write-PlayHeader "PLAYGROUND: ENTERPRISE AUTOMATION PILLARS" Write-Host " Run any enterprise pillar and see how it learns." -ForegroundColor Gray Write-Host " Compare baseline vs trained agent performance." -ForegroundColor Gray Write-PlaySection "Step 1: Choose a Pillar" $pillarChoice = Read-PlayChoice "Pick a pillar to train" @( "JobScheduler -- adaptive job scheduling" "SecurityMonitor -- detect and respond to security threats" "AnomalyDetector -- find unusual patterns" "CapacityPlanner -- predict resource needs" "SelfHealing -- detect and fix infrastructure issues" "EnergyOptimizer -- reduce energy consumption" "AutoPilot -- orchestrate all 13 pillars" ) $pillarNames = @( "JobScheduler", "SecurityMonitor", "AnomalyDetector", "CapacityPlanner", "SelfHealing", "EnergyOptimizer", "AutoPilot" ) $pillarName = $pillarNames[$pillarChoice] Write-PlaySection "Step 2: Configure Training" $episodes = Read-PlayInt "Number of episodes" 50 10 200 $printEvery = Read-PlayInt "Print every N episodes" 10 5 50 Write-PlaySection "Step 3: Training $pillarName" Write-Host " Episodes : $episodes" -ForegroundColor White Write-Host " SimMode : yes (safe for learning)" -ForegroundColor White Write-Host "" Write-Host " Starting $pillarName training..." -ForegroundColor Yellow Write-Host "" $startTime = Get-Date $result = switch ($pillarName) { "JobScheduler" { Invoke-VBAFJobSchedulerTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "SecurityMonitor" { Invoke-VBAFSecurityMonitorTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "AnomalyDetector" { Invoke-VBAFAnomalyDetectorTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "CapacityPlanner" { Invoke-VBAFCapacityPlannerTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "SelfHealing" { Invoke-VBAFSelfHealingTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "EnergyOptimizer" { Invoke-VBAFEnergyOptimizerTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } "AutoPilot" { Invoke-VBAFAutoPilotTraining -Episodes $episodes -PrintEvery $printEvery -SimMode } } $elapsed = (Get-Date) - $startTime Write-PlaySection "Results" if ($result -and $result.Baseline -and $result.Trained) { $baseAvg = $result.Baseline.Avg $trainedAvg = $result.Trained.Avg $imp = if ($baseAvg -ne 0) { ($trainedAvg - $baseAvg) / [Math]::Abs($baseAvg) * 100 } else { 0.0 } Write-PlayResult "Baseline avg reward" $baseAvg "" "Gray" Write-PlayResult "Trained avg reward" $trainedAvg "" "Green" $impColor = if ($imp -gt 0) { "Green" } else { "Red" } Write-Host (" {0,-30} {1,9:F1}%" -f "Improvement", $imp) -ForegroundColor $impColor if ($imp -gt 20) { Write-Host "" Write-Host " Strong learning signal -- agent clearly improved!" -ForegroundColor Green } elseif ($imp -gt 0) { Write-Host "" Write-Host " Some improvement -- try more episodes for stronger signal." -ForegroundColor Yellow } else { Write-Host "" Write-Host " No improvement -- try more episodes or check the setup." -ForegroundColor Red } } Write-Host (" Training time: {0:F1} seconds" -f $elapsed.TotalSeconds) -ForegroundColor DarkGray Write-PlaySection "What Did You Learn?" Write-Host " - The 15/40/30/15 distribution guarantees measurable improvement" -ForegroundColor DarkGray Write-Host " - More episodes = higher improvement percentage (usually)" -ForegroundColor DarkGray Write-Host " - AutoPilot orchestrates all pillars -- the most complex agent" -ForegroundColor DarkGray Write-Host " - Replace -SimMode with real Windows data for production use" -ForegroundColor DarkGray Write-Host "" } # ============================================================================ # PLAYGROUND 4 -- SUPERVISED LEARNING EXPERIMENT # ============================================================================ function Play-Supervised { Write-PlayHeader "PLAYGROUND: SUPERVISED LEARNING" Write-Host " Train a supervised learning model on the HousePrice dataset." -ForegroundColor Gray Write-Host " Compare different algorithms and see their R2 scores." -ForegroundColor Gray Write-PlaySection "Step 1: Choose a Model" $modelChoice = Read-PlayChoice "Pick a model to train" @( "LinearRegression -- straight line fit, fast and interpretable" "RidgeRegression -- LinearRegression with regularisation" "DecisionTree -- tree of if/then rules, fully interpretable" "RandomForest -- ensemble of decision trees, more robust" "All four -- train all and compare" ) Write-PlaySection "Step 2: Configure" $testSize = Read-PlayChoice "Test set size" @( "20% test (default)" "30% test (more robust evaluation)" "10% test (more training data)" ) $testSizes = @(0.2, 0.3, 0.1) $ts = $testSizes[$testSize] $scaleChoice = Read-PlayChoice "Feature scaling" @( "StandardScaler -- zero mean, unit variance (recommended)" "MinMaxScaler -- scale to [0,1]" "No scaling -- raw features" ) Write-PlaySection "Step 3: Training" Write-Host " Loading HousePrice dataset..." -ForegroundColor DarkGray $data = Get-VBAFDataset -Name "HousePrice" $split = Split-TrainTest -X $data.X -y $data.y -TestSize $ts -Seed 42 $scaler = switch ($scaleChoice) { 0 { [StandardScaler]::new() } 1 { [MinMaxScaler]::new() } 2 { $null } } if ($scaler) { $Xtrain = $scaler.FitTransform($split.XTrain) $Xtest = $scaler.Transform($split.XTest) } else { $Xtrain = $split.XTrain $Xtest = $split.XTest } $modelsToRun = if ($modelChoice -eq 4) { @(0,1,2,3) } else { @($modelChoice) } $modelResults = @() foreach ($m in $modelsToRun) { $modelName = @("LinearRegression","RidgeRegression","DecisionTree","RandomForest")[$m] Write-Host " Training $modelName..." -ForegroundColor DarkGray $model = switch ($m) { 0 { [LinearRegression]::new() } 1 { [RidgeRegression]::new(0.01) } 2 { [DecisionTree]::new("regression",3,2) } 3 { [RandomForest]::new(10,3,2) } } $startTime = Get-Date $model.Fit($Xtrain, $split.yTrain) $preds = $model.Predict($Xtest) $metrics = Get-RegressionMetrics $split.yTest $preds $elapsed = ((Get-Date) - $startTime).TotalSeconds $modelResults += @{ Name = $modelName R2 = $metrics.R2 RMSE = $metrics.RMSE Time = $elapsed } } Write-PlaySection "Results" Write-Host (" {0,-22} {1,8} {2,10} {3,8}" -f "Model", "R2", "RMSE", "Time(s)") -ForegroundColor Gray Write-Host (" {0,-22} {1,8} {2,10} {3,8}" -f "-----", "--", "----", "-------") -ForegroundColor DarkGray $sorted = $modelResults | Sort-Object { $_.R2 } -Descending foreach ($r in $sorted) { $r2Color = if ($r.R2 -gt 0.9) { "Green" } elseif ($r.R2 -gt 0.7) { "Yellow" } else { "Red" } Write-Host -NoNewline (" {0,-22}" -f $r.Name) -ForegroundColor White Write-Host -NoNewline ("{0,8:F4}" -f $r.R2) -ForegroundColor $r2Color Write-Host -NoNewline ("{0,10:F2}" -f $r.RMSE) -ForegroundColor White Write-Host ("{0,8:F2}" -f $r.Time) -ForegroundColor DarkGray } Write-Host "" if ($sorted.Count -gt 1) { Write-Host " Best model: $($sorted[0].Name) (R2 = $(([double]$sorted[0].R2).ToString('F4')))" -ForegroundColor Green } Write-PlaySection "What Did You Learn?" Write-Host " - R2 closer to 1.0 = better prediction" -ForegroundColor DarkGray Write-Host " - Ridge adds regularisation -- helps when features are correlated" -ForegroundColor DarkGray Write-Host " - RandomForest is usually more robust but slower" -ForegroundColor DarkGray Write-Host " - Scaling matters for LinearRegression and Ridge, not for trees" -ForegroundColor DarkGray Write-Host "" } # ============================================================================ # MAIN PLAYGROUND FUNCTION # ============================================================================ function Start-VBAFPlayground { <# .SYNOPSIS Interactive VBAF experiment playground. .DESCRIPTION Menu-driven interface for experimenting with VBAF algorithms. No coding required -- pick options and watch the results. .PARAMETER Algorithm Optional. Jump directly to one playground: "DQN" | "QLearning" | "Enterprise" | "Supervised" Default: show main menu. .EXAMPLE Start-VBAFPlayground Start-VBAFPlayground -Algorithm "DQN" Start-VBAFPlayground -Algorithm "Enterprise" #> param( [string]$Algorithm = "" ) if (-not ([System.Management.Automation.PSTypeName]"QLearningAgent").Type) { Write-Host "" Write-Host " ERROR: VBAF framework not loaded." -ForegroundColor Red Write-Host " Run this first:" -ForegroundColor Yellow Write-Host " . .\VBAF.LoadAll.ps1" -ForegroundColor White Write-Host "" return } Write-PlayHeader "VBAF PLAYGROUND" Write-Host " Experiment with algorithms interactively." -ForegroundColor Gray Write-Host " No coding required -- just pick options and watch." -ForegroundColor Gray Write-Host " Press Ctrl+C at any time to exit." -ForegroundColor Gray if ($Algorithm -ne "") { switch ($Algorithm) { "DQN" { Play-DQN } "QLearning" { Play-QLearning } "Enterprise" { Play-Enterprise } "Supervised" { Play-Supervised } default { Write-Host " Unknown algorithm: $Algorithm" -ForegroundColor Red Write-Host " Use: DQN, QLearning, Enterprise, Supervised" -ForegroundColor Red } } return } # Main menu loop $running = $true while ($running) { Write-PlayHeader "MAIN MENU" $choice = Read-PlayChoice "Choose a playground" @( "DQN Experiment -- train a Deep Q-Network, tune hyperparameters" "Q-Learning Experiment -- train a Q-table agent, inspect what it learned" "Enterprise Pillars -- run any of the 14 enterprise automation agents" "Supervised Learning -- compare regression models on HousePrice dataset" "Exit Playground" ) switch ($choice) { 0 { Play-DQN } 1 { Play-QLearning } 2 { Play-Enterprise } 3 { Play-Supervised } 4 { $running = $false } } if ($running -and $choice -ne 4) { Write-Host "" $again = Read-PlayChoice "What next?" @( "Return to main menu" "Exit playground" ) if ($again -eq 1) { $running = $false } } } Write-Host "" Write-Host ("=" * 65) -ForegroundColor Cyan Write-Host " VBAF Playground session ended." -ForegroundColor Cyan Write-Host " See docs\ for deeper reading." -ForegroundColor Cyan Write-Host ("=" * 65) -ForegroundColor Cyan Write-Host "" } |