cwenzi/neuroflow-cpp
1
1#include <iostream>2#include <chrono>3#include "../include/neuroflow/model.hpp"4#include "../include/neuroflow/backprop.hpp"5 6using namespace neuroflow;7 8void test_forward_cache() {9 std::cout << "\n=== Forward Cache Test ===\n";10 11 NeuroFlowModel::Config cfg;12 cfg.input_dim = 64;13 cfg.hidden_dim = 32;14 cfg.output_dim = 5;15 cfg.memory_dim = 32;16 cfg.num_layers = 1;17 cfg.num_associations = 2;18 19 NeuroFlowModel model(cfg);20 FullBackpropEngine bp(model);21 22 Tensor input({2, 64});23 float* data = input.as_fp32();24 for (size_t i = 0; i < input.numel(); ++i) {25 data[i] = 0.1f * i;26 }27 28 auto output = bp.forward_with_cache(input);29 30 std::cout << " Forward cache stored:\n";31 std::cout << " input: [" << bp.cache.input.shape_[0] << ", " << bp.cache.input.shape_[1] << "]\n";32 std::cout << " h: [" << bp.cache.h.shape_[0] << ", " << bp.cache.h.shape_[1] << "]\n";33 std::cout << " ecn_hidden: " << bp.cache.ecn_hidden.size() << " layers\n";34 std::cout << " combined: [" << bp.cache.combined.shape_[0] << ", " << bp.cache.combined.shape_[1] << "]\n";35 36 std::cout << " Output shape: [" << output.output.shape_[0] 37 << ", " << output.output.shape_[1] << "]\n";38 39 std::cout << " [PASS] Forward cache works\n";40}41 42void test_backward_pass() {43 std::cout << "\n=== Backward Pass Test ===\n";44 45 NeuroFlowModel::Config cfg;46 cfg.input_dim = 64;47 cfg.hidden_dim = 32;48 cfg.output_dim = 5;49 cfg.memory_dim = 32;50 cfg.num_layers = 1;51 cfg.num_associations = 2;52 53 NeuroFlowModel model(cfg);54 FullBackpropEngine bp(model);55 56 Tensor input({2, 64});57 for (size_t i = 0; i < input.numel(); ++i) {58 input.as_fp32()[i] = 0.1f * i;59 }60 61 auto output = bp.forward_with_cache(input);62 63 Tensor output_grad({2, 5});64 for (size_t i = 0; i < output_grad.numel(); ++i) {65 output_grad.as_fp32()[i] = 0.01f;66 }67 68 auto grads = bp.backward(output_grad);69 70 std::cout << " Backward gradients computed:\n";71 std::cout << " output_fusion_down_weight_grad: [" << grads.output_fusion_down_weight_grad.shape_[0] 72 << ", " << grads.output_fusion_down_weight_grad.shape_[1] << "]\n";73 std::cout << " output_fusion_up_weight_grad: [" << grads.output_fusion_up_weight_grad.shape_[0] 74 << ", " << grads.output_fusion_up_weight_grad.shape_[1] << "]\n";75 std::cout << " input_grad: [" << grads.input_grad.shape_[0] 76 << ", " << grads.input_grad.shape_[1] << "]\n";77 78 float grad_sum = 0;79 const float* wg = grads.output_fusion_down_weight_grad.as_fp32();80 for (size_t i = 0; i < grads.output_fusion_down_weight_grad.numel(); ++i) {81 grad_sum += std::abs(wg[i]);82 }83 std::cout << " Total weight gradient magnitude: " << grad_sum << "\n";84 85 std::cout << " [PASS] Backward pass works\n";86}87 88void test_trainer() {89 std::cout << "\n=== FullTrainer Test ===\n";90 91 NeuroFlowModel::Config cfg;92 cfg.input_dim = 64;93 cfg.hidden_dim = 32;94 cfg.output_dim = 5;95 cfg.memory_dim = 32;96 cfg.num_layers = 1;97 cfg.num_associations = 2;98 99 NeuroFlowModel model(cfg);100 FullTrainer trainer(model, 0.01f);101 102 Tensor input({2, 64});103 Tensor target({2, 5});104 105 std::mt19937 rng(42);106 std::uniform_real_distribution<float> dist(-0.05f, 0.05f);107 for (size_t i = 0; i < input.numel(); ++i) {108 input.as_fp32()[i] = dist(rng);109 }110 for (size_t i = 0; i < target.numel(); ++i) {111 target.as_fp32()[i] = (i % 5 == 2) ? 1.0f : 0.0f;112 }113 114 auto output1 = model.forward(input);115 float loss1 = LossFunctions::mse(output1.output, target);116 117 std::cout << " Training for 10 steps...\n";118 for (int i = 0; i < 10; ++i) {119 auto step = trainer.train_step(input, target);120 std::cout << " Step " << i << ": loss=" << step.loss 121 << ", grad_norm=" << step.grad_norm << "\n";122 }123 124 auto output2 = model.forward(input);125 float loss2 = LossFunctions::mse(output2.output, target);126 127 std::cout << " Initial loss: " << loss1 << "\n";128 std::cout << " Final loss: " << loss2 << "\n";129 std::cout << " Loss reduction: " << (loss1 - loss2) << "\n";130 131 if (loss2 <= loss1) {132 std::cout << " [PASS] Training reduces loss\n";133 } else {134 std::cout << " [WARN] Loss increased\n";135 }136}137 138void test_memory_consolidation_training() {139 std::cout << "\n=== Memory Consolidation Training Test ===\n";140 141 NeuroFlowModel::Config cfg;142 cfg.input_dim = 64;143 cfg.hidden_dim = 32;144 cfg.output_dim = 5;145 cfg.memory_slots = 16;146 cfg.memory_dim = 16;147 148 NeuroFlowModel model(cfg);149 FullTrainer trainer(model, 0.01f);150 151 std::cout << " Initial memory bank sample: " << model.memory->memory_bank.as_fp32()[0] << "\n";152 153 std::mt19937 rng(123);154 std::uniform_real_distribution<float> dist(-0.05f, 0.05f);155 std::uniform_real_distribution<float> dist01(0.0f, 1.0f);156 157 for (int batch = 0; batch < 5; ++batch) {158 Tensor input({4, 64});159 Tensor target({4, 5});160 161 for (size_t i = 0; i < input.numel(); ++i) {162 input.as_fp32()[i] = dist(rng);163 }164 for (size_t i = 0; i < target.numel(); ++i) {165 target.as_fp32()[i] = dist01(rng);166 }167 168 auto step = trainer.train_step(input, target);169 std::cout << " Batch " << batch << ": loss=" << step.loss << "\n";170 }171 172 float mem_after = model.memory->memory_bank.as_fp32()[0];173 std::cout << " Memory bank after training: " << mem_after << "\n";174 std::cout << " Memory slots: " << model.memory->memory_slots << "\n";175 176 std::cout << " [PASS] Memory consolidation during training\n";177}178 179void test_gradient_flow() {180 std::cout << "\n=== Gradient Flow Test ===\n";181 182 NeuroFlowModel::Config cfg;183 cfg.input_dim = 32;184 cfg.hidden_dim = 16;185 cfg.output_dim = 3;186 cfg.num_layers = 2;187 188 NeuroFlowModel model(cfg);189 FullBackpropEngine bp(model);190 191 Tensor input({1, 32});192 for (size_t i = 0; i < 32; ++i) input.as_fp32()[i] = 0.1f;193 194 auto output = bp.forward_with_cache(input);195 196 Tensor output_grad({1, 3});197 output_grad.as_fp32()[0] = 1.0f;198 output_grad.as_fp32()[1] = 0.0f;199 output_grad.as_fp32()[2] = -1.0f;200 201 auto grads = bp.backward(output_grad);202 203 std::cout << " Input gradient samples:\n";204 const float* ig = grads.input_grad.as_fp32();205 for (size_t i = 0; i < 5; ++i) {206 std::cout << " grad[" << i << "] = " << ig[i] << "\n";207 }208 209 std::cout << " [PASS] Gradient flows to input\n";210}211 212int main() {213 std::cout << "========================================\n";214 std::cout << "NeuroFlow Backpropagation Tests\n";215 std::cout << "========================================\n";216 217 test_forward_cache();218 test_backward_pass();219 test_trainer();220 test_memory_consolidation_training();221 test_gradient_flow();222 223 std::cout << "\n========================================\n";224 std::cout << "All Tests Complete!\n";225 std::cout << "========================================\n";226 227 return 0;228}229 