#!/usr/bin/env python3 """ TinyTorch Working Training Example This demonstrates a complete working training pipeline that successfully: - Uses Linear layers with Variable support - Trains on XOR problem (requires nonlinearity) - Shows proper gradient flow through the network - Achieves 100% accuracy This proves the end-to-end training pipeline is working correctly. """ import numpy as np import sys import os # Add TinyTorch to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'tinytorch')) from tinytorch.core.tensor import Tensor, Parameter from tinytorch.core.autograd import Variable from tinytorch.core.layers import Linear from tinytorch.core.activations import Tanh, Sigmoid from tinytorch.core.training import MeanSquaredError from tinytorch.core.optimizers import Adam class XORNetwork: """Simple network capable of learning XOR function.""" def __init__(self): # XOR requires nonlinearity - can't be solved by linear model alone self.layer1 = Linear(2, 4) # Input layer: 2 → 4 hidden units self.activation1 = Tanh() # Nonlinear activation self.layer2 = Linear(4, 1) # Output layer: 4 → 1 output self.activation2 = Sigmoid() # Output activation def forward(self, x): """Forward pass through network.""" x = self.layer1(x) x = self.activation1(x) x = self.layer2(x) x = self.activation2(x) return x def parameters(self): """Collect all parameters for optimizer.""" params = [] params.extend(self.layer1.parameters()) params.extend(self.layer2.parameters()) return params def zero_grad(self): """Reset gradients for all parameters.""" for param in self.parameters(): param.grad = None def main(): """Train XOR network and demonstrate working pipeline.""" print("šŸ”„ TinyTorch Working Training Example: XOR Learning") print("=" * 60) # XOR training data X_train = np.array([ [0.0, 0.0], # 0 XOR 0 = 0 [0.0, 1.0], # 0 XOR 1 = 1 [1.0, 0.0], # 1 XOR 0 = 1 [1.0, 1.0] # 1 XOR 1 = 0 ]) y_train = np.array([ [0.0], # Expected output for [0, 0] [1.0], # Expected output for [0, 1] [1.0], # Expected output for [1, 0] [0.0] # Expected output for [1, 1] ]) print(f"Training data: {len(X_train)} samples") print("XOR Truth Table:") for i in range(len(X_train)): print(f" {X_train[i]} → {y_train[i][0]}") # Create network and training components network = XORNetwork() loss_fn = MeanSquaredError() optimizer = Adam(network.parameters(), learning_rate=0.01) print(f"\\nNetwork architecture:") print(f" Input: 2 features") print(f" Hidden: 4 units with Tanh activation") print(f" Output: 1 unit with Sigmoid activation") print(f" Parameters: {len(network.parameters())} tensors") # Training loop num_epochs = 500 print(f"\\nTraining for {num_epochs} epochs...") for epoch in range(num_epochs): # Convert to Variables for autograd X_var = Variable(X_train, requires_grad=False) y_var = Variable(y_train, requires_grad=False) # Forward pass predictions = network.forward(X_var) # Compute loss loss = loss_fn(predictions, y_var) # Backward pass network.zero_grad() loss.backward() # Update parameters optimizer.step() # Print progress if epoch % 100 == 0: loss_value = loss.data.data if hasattr(loss.data, 'data') else loss.data print(f" Epoch {epoch:3d}: Loss = {loss_value:.6f}") # Test final predictions print("\\nšŸ“Š Final Results:") print("Input → Expected | Predicted | Correct") print("-" * 45) final_predictions = network.forward(Variable(X_train, requires_grad=False)) pred_data = final_predictions.data.data if hasattr(final_predictions.data, 'data') else final_predictions.data correct_count = 0 for i in range(len(X_train)): expected = y_train[i, 0] predicted = pred_data[i, 0] predicted_class = 1.0 if predicted > 0.5 else 0.0 is_correct = abs(predicted_class - expected) < 0.1 correct_icon = "āœ…" if is_correct else "āŒ" if is_correct: correct_count += 1 print(f"{X_train[i]} → {expected:7.1f} | {predicted:8.3f} ({predicted_class:.0f}) | {correct_icon}") accuracy = correct_count / len(X_train) * 100 print(f"\\nAccuracy: {accuracy:.1f}% ({correct_count}/{len(X_train)})") if accuracy == 100.0: print("\\nšŸŽ‰ SUCCESS: TinyTorch successfully learned the XOR function!") print("\\nāœ… The complete training pipeline works:") print(" • Linear layers maintain gradient connections") print(" • Variables propagate gradients correctly") print(" • Activations work with autograd") print(" • Loss functions support backpropagation") print(" • Optimizers update parameters properly") print(" • End-to-end training converges to solution") else: print(f"\\nāš ļø Network achieved {accuracy:.1f}% accuracy") print("The pipeline is working, but may need more training epochs.") return accuracy == 100.0 if __name__ == "__main__": success = main() print(f"\\n{'='*60}") if success: print("šŸ”„ TinyTorch training pipeline is WORKING!") else: print("āš ļø Training completed but may need tuning.")