notRaphael commited on
Commit
e5dcb32
Β·
verified Β·
1 Parent(s): adb35ab

Upload main.cpp

Browse files
Files changed (1) hide show
  1. main.cpp +184 -0
main.cpp ADDED
@@ -0,0 +1,184 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ===========================================================================
2
+ // newnet β€” Neural Network from Scratch
3
+ //
4
+ // Compile: g++ -std=c++17 -O2 -pthread -o newnet main.cpp
5
+ // Run: ./newnet
6
+ //
7
+ // This trains a small network on the XOR problem to prove:
8
+ // 1. Forward pass works (matmul + bias + activation)
9
+ // 2. Backward pass works (chain rule, gradient computation)
10
+ // 3. Optimizer works (weights update, loss decreases)
11
+ // 4. Non-linear problems are solvable (XOR needs hidden layers)
12
+ // ===========================================================================
13
+
14
+ #include "core/tensor.hpp"
15
+ #include "core/backend.hpp"
16
+ #include "layers/dense.hpp"
17
+ #include "graph/graph.hpp"
18
+ #include "graph/optimizer.hpp"
19
+ #include "loss/loss.hpp"
20
+
21
+ #include <iostream>
22
+ #include <iomanip>
23
+ #include <chrono>
24
+ #include <string>
25
+
26
+ using namespace newnet;
27
+
28
+ // --- Progress bar ---
29
+ void print_progress(int epoch, int total_epochs, float loss, float elapsed_ms) {
30
+ int bar_width = 30;
31
+ float progress = (float)(epoch + 1) / total_epochs;
32
+ int filled = (int)(bar_width * progress);
33
+
34
+ std::cout << "\r [";
35
+ for (int i = 0; i < bar_width; i++) {
36
+ if (i < filled) std::cout << "β–ˆ";
37
+ else std::cout << "β–‘";
38
+ }
39
+ std::cout << "] "
40
+ << std::setw(4) << epoch + 1 << "/" << total_epochs
41
+ << " | loss: " << std::fixed << std::setprecision(6) << loss
42
+ << " | " << std::fixed << std::setprecision(1) << elapsed_ms << "ms"
43
+ << std::flush;
44
+ }
45
+
46
+ // --- Print predictions ---
47
+ void print_predictions(Sequential& net, const Tensor& input, const Tensor& target) {
48
+ Tensor output = net.forward(input);
49
+
50
+ std::cout << "\n β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”\n";
51
+ std::cout << " β”‚ Input β”‚ Predicted β”‚ Target β”‚ Correct β”‚\n";
52
+ std::cout << " β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€\n";
53
+
54
+ int correct = 0;
55
+ for (int i = 0; i < input.rows(); i++) {
56
+ float pred = output(i, 0);
57
+ float tgt = target(i, 0);
58
+ bool is_correct = (pred > 0.5f) == (tgt > 0.5f);
59
+ if (is_correct) correct++;
60
+
61
+ std::cout << " β”‚ ["
62
+ << std::fixed << std::setprecision(0) << input(i, 0) << ", "
63
+ << input(i, 1) << "]"
64
+ << " β”‚ " << std::fixed << std::setprecision(4) << pred
65
+ << " β”‚ " << std::fixed << std::setprecision(4) << tgt
66
+ << " β”‚ " << (is_correct ? "βœ“" : "βœ—") << " β”‚\n";
67
+ }
68
+
69
+ std::cout << " β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜\n";
70
+ std::cout << " Accuracy: " << correct << "/" << input.rows()
71
+ << " (" << (100.0f * correct / input.rows()) << "%)\n";
72
+ }
73
+
74
+ int main() {
75
+ std::cout << "\n";
76
+ std::cout << " ╔═══════════════════════════════════════════════╗\n";
77
+ std::cout << " β•‘ newnet v0.1 β€” Training Demo β•‘\n";
78
+ std::cout << " β•‘ Neural Network Engine from Scratch (C++) β•‘\n";
79
+ std::cout << " β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•\n\n";
80
+
81
+ std::cout << " Hardware threads: " << std::thread::hardware_concurrency() << "\n";
82
+ std::cout << " Backend: CPU (multi-threaded)\n\n";
83
+
84
+ // =========================================================================
85
+ // Dataset: XOR
86
+ // This is the simplest non-linear classification problem.
87
+ // A single layer (linear model) CANNOT solve this.
88
+ // You need at least one hidden layer β€” proving our NN works.
89
+ // =========================================================================
90
+
91
+ std::cout << " ── Dataset: XOR ──────────────────────────────────\n\n";
92
+
93
+ Tensor input({4, 2});
94
+ input(0,0) = 0; input(0,1) = 0; // 0 XOR 0 = 0
95
+ input(1,0) = 0; input(1,1) = 1; // 0 XOR 1 = 1
96
+ input(2,0) = 1; input(2,1) = 0; // 1 XOR 0 = 1
97
+ input(3,0) = 1; input(3,1) = 1; // 1 XOR 1 = 0
98
+
99
+ Tensor target({4, 1});
100
+ target(0,0) = 0;
101
+ target(1,0) = 1;
102
+ target(2,0) = 1;
103
+ target(3,0) = 0;
104
+
105
+ std::cout << " Samples: 4 | Features: 2 | Output: 1 (binary)\n\n";
106
+
107
+ // =========================================================================
108
+ // Model: 2 β†’ 16 (relu) β†’ 8 (relu) β†’ 1 (sigmoid)
109
+ // =========================================================================
110
+
111
+ std::cout << " ── Model Architecture ────────────────────────────\n\n";
112
+ std::cout << " Input(2) β†’ Dense(16, relu) β†’ Dense(8, relu) β†’ Dense(1, sigmoid)\n";
113
+ std::cout << " Parameters: " << (2*16+16) + (16*8+8) + (8*1+1) << " total\n\n";
114
+
115
+ Sequential net;
116
+ net.add(new Dense(2, 16, "relu"));
117
+ net.add(new Dense(16, 8, "relu"));
118
+ net.add(new Dense(8, 1, "sigmoid"));
119
+
120
+ // =========================================================================
121
+ // Training
122
+ // =========================================================================
123
+
124
+ std::cout << " ── Training ──────────────────────────────────────\n\n";
125
+ std::cout << " Optimizer: Adam (lr=0.01)\n";
126
+ std::cout << " Loss: MSE\n";
127
+ std::cout << " Epochs: 2000\n\n";
128
+
129
+ Adam optimizer(0.01f);
130
+ MSELoss loss_fn;
131
+
132
+ int epochs = 2000;
133
+ auto train_start = std::chrono::high_resolution_clock::now();
134
+
135
+ float final_loss = 0.0f;
136
+
137
+ for (int epoch = 0; epoch < epochs; epoch++) {
138
+ // 1. Zero gradients from previous iteration
139
+ optimizer.zero_grad(net.parameters());
140
+
141
+ // 2. Forward pass
142
+ Tensor output = net.forward(input);
143
+
144
+ // 3. Compute loss
145
+ float loss = loss_fn.forward(output, target);
146
+ final_loss = loss;
147
+
148
+ // 4. Backward pass β€” compute gradients via chain rule
149
+ Tensor grad = loss_fn.backward();
150
+ net.backward(grad);
151
+
152
+ // 5. Update weights
153
+ optimizer.step(net.parameters());
154
+
155
+ // Progress bar update
156
+ if (epoch % 50 == 0 || epoch == epochs - 1) {
157
+ auto now = std::chrono::high_resolution_clock::now();
158
+ float elapsed = std::chrono::duration<float, std::milli>(now - train_start).count();
159
+ print_progress(epoch, epochs, loss, elapsed);
160
+ }
161
+ }
162
+
163
+ auto train_end = std::chrono::high_resolution_clock::now();
164
+ float total_ms = std::chrono::duration<float, std::milli>(train_end - train_start).count();
165
+
166
+ std::cout << "\n\n Training complete in " << std::fixed << std::setprecision(1)
167
+ << total_ms << "ms\n";
168
+ std::cout << " Final loss: " << std::fixed << std::setprecision(6) << final_loss << "\n\n";
169
+
170
+ // =========================================================================
171
+ // Results
172
+ // =========================================================================
173
+
174
+ std::cout << " ── Predictions ───────────────────────────────────\n";
175
+ print_predictions(net, input, target);
176
+
177
+ std::cout << "\n ── Summary ───────────────────────────────────────\n\n";
178
+ std::cout << " If predictions are close to targets (>0.5 = 1, <0.5 = 0),\n";
179
+ std::cout << " then forward pass, backward pass, and optimizer all work.\n";
180
+ std::cout << " XOR is non-linear β€” a single Dense layer cannot solve it.\n";
181
+ std::cout << " The hidden layers learned the non-linear decision boundary.\n\n";
182
+
183
+ return 0;
184
+ }