ProCreations commited on
Commit
7045893
·
verified ·
1 Parent(s): 8b22d98

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +844 -0
index.html CHANGED
@@ -0,0 +1,844 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Explainer: How Neural Networks Work</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+ body {
14
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
15
+ background: #0a0a0a;
16
+ color: #e0e0e0;
17
+ line-height: 1.6;
18
+ overflow-x: hidden;
19
+ }
20
+ .container {
21
+ max-width: 1200px;
22
+ margin: 0 auto;
23
+ padding: 20px;
24
+ }
25
+ header {
26
+ text-align: center;
27
+ padding: 40px 20px;
28
+ background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
29
+ margin-bottom: 40px;
30
+ border-radius: 20px;
31
+ }
32
+ h1 {
33
+ font-size: clamp(2rem, 5vw, 3rem);
34
+ margin-bottom: 10px;
35
+ background: linear-gradient(135deg, #fff 0%, #a8dadc 100%);
36
+ -webkit-background-clip: text;
37
+ -webkit-text-fill-color: transparent;
38
+ }
39
+ .mode-toggle {
40
+ display: flex;
41
+ justify-content: center;
42
+ gap: 20px;
43
+ margin: 30px 0;
44
+ flex-wrap: wrap;
45
+ }
46
+ .mode-btn {
47
+ padding: 12px 30px;
48
+ background: #2a5298;
49
+ color: white;
50
+ border: none;
51
+ border-radius: 50px;
52
+ cursor: pointer;
53
+ font-size: 16px;
54
+ transition: all 0.3s ease;
55
+ font-weight: 600;
56
+ }
57
+ .mode-btn.active {
58
+ background: #4CAF50;
59
+ transform: scale(1.05);
60
+ }
61
+ .mode-btn:hover {
62
+ transform: translateY(-2px);
63
+ box-shadow: 0 5px 15px rgba(74, 144, 226, 0.3);
64
+ }
65
+ .section {
66
+ background: #1a1a1a;
67
+ padding: 30px;
68
+ margin-bottom: 30px;
69
+ border-radius: 20px;
70
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
71
+ }
72
+ .section h2 {
73
+ color: #4CAF50;
74
+ margin-bottom: 20px;
75
+ font-size: clamp(1.5rem, 4vw, 2rem);
76
+ }
77
+ .section h3 {
78
+ color: #81C784;
79
+ margin: 20px 0 10px 0;
80
+ font-size: clamp(1.2rem, 3vw, 1.5rem);
81
+ }
82
+ .math-content {
83
+ background: #0d0d0d;
84
+ padding: 20px;
85
+ border-radius: 10px;
86
+ overflow-x: auto;
87
+ margin: 15px 0;
88
+ border: 1px solid #333;
89
+ }
90
+ .learn-content {
91
+ background: #1e3c72;
92
+ padding: 20px;
93
+ border-radius: 10px;
94
+ margin: 15px 0;
95
+ line-height: 1.8;
96
+ }
97
+ #xor-demo {
98
+ background: #0d0d0d;
99
+ padding: 20px;
100
+ border-radius: 15px;
101
+ margin: 20px 0;
102
+ }
103
+ #network-canvas {
104
+ width: 100%;
105
+ max-width: 800px;
106
+ height: 400px;
107
+ background: #000;
108
+ border-radius: 10px;
109
+ margin: 20px auto;
110
+ display: block;
111
+ }
112
+ .controls {
113
+ display: flex;
114
+ gap: 15px;
115
+ justify-content: center;
116
+ flex-wrap: wrap;
117
+ margin: 20px 0;
118
+ }
119
+ .control-btn {
120
+ padding: 10px 25px;
121
+ background: #4CAF50;
122
+ color: white;
123
+ border: none;
124
+ border-radius: 5px;
125
+ cursor: pointer;
126
+ font-size: 16px;
127
+ transition: all 0.3s ease;
128
+ }
129
+ .control-btn:hover {
130
+ background: #45a049;
131
+ transform: translateY(-2px);
132
+ }
133
+ .control-btn:disabled {
134
+ background: #666;
135
+ cursor: not-allowed;
136
+ }
137
+ .stats {
138
+ display: grid;
139
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
140
+ gap: 15px;
141
+ margin: 20px 0;
142
+ }
143
+ .stat-box {
144
+ background: #1a1a1a;
145
+ padding: 15px;
146
+ border-radius: 10px;
147
+ text-align: center;
148
+ border: 1px solid #333;
149
+ }
150
+ .stat-label {
151
+ color: #888;
152
+ font-size: 14px;
153
+ }
154
+ .stat-value {
155
+ color: #4CAF50;
156
+ font-size: 24px;
157
+ font-weight: bold;
158
+ margin-top: 5px;
159
+ }
160
+ .loss-chart {
161
+ width: 100%;
162
+ height: 200px;
163
+ background: #000;
164
+ border-radius: 10px;
165
+ margin: 20px 0;
166
+ }
167
+ .formula {
168
+ font-family: 'Courier New', monospace;
169
+ color: #64B5F6;
170
+ padding: 10px;
171
+ background: rgba(0, 0, 0, 0.5);
172
+ border-radius: 5px;
173
+ overflow-x: auto;
174
+ white-space: nowrap;
175
+ margin: 10px 0;
176
+ }
177
+ .highlight {
178
+ background: #4CAF50;
179
+ color: #000;
180
+ padding: 2px 6px;
181
+ border-radius: 3px;
182
+ font-weight: bold;
183
+ }
184
+ @media (max-width: 768px) {
185
+ .container {
186
+ padding: 10px;
187
+ }
188
+
189
+ .section {
190
+ padding: 20px;
191
+ }
192
+
193
+ #network-canvas {
194
+ height: 300px;
195
+ }
196
+
197
+ .controls {
198
+ gap: 10px;
199
+ }
200
+
201
+ .control-btn {
202
+ padding: 8px 20px;
203
+ font-size: 14px;
204
+ }
205
+ }
206
+ .mode-content {
207
+ display: none;
208
+ }
209
+ .mode-content.active {
210
+ display: block;
211
+ }
212
+ .animated-number {
213
+ transition: all 0.3s ease;
214
+ }
215
+ @keyframes pulse {
216
+ 0% { transform: scale(1); }
217
+ 50% { transform: scale(1.1); }
218
+ 100% { transform: scale(1); }
219
+ }
220
+ .pulse {
221
+ animation: pulse 0.5s ease;
222
+ }
223
+ </style>
224
+ </head>
225
+ <body>
226
+ <div class="container">
227
+ <header>
228
+ <h1>🧠 How AI Really Works</h1>
229
+ <p>An Interactive Journey Inside Neural Networks</p>
230
+ </header>
231
+
232
+ <div class="mode-toggle">
233
+ <button class="mode-btn active" onclick="setMode('learn')">🎓 Learn Mode</button>
234
+ <button class="mode-btn" onclick="setMode('math')">🔢 Math Mode</button>
235
+ </div>
236
+
237
+ <div class="section">
238
+ <h2>What is a Neural Network?</h2>
239
+
240
+ <div class="mode-content learn-mode active">
241
+ <div class="learn-content">
242
+ <p>Imagine your brain is made of billions of tiny decision-makers called neurons. Each neuron:</p>
243
+ <ul style="margin: 15px 0; padding-left: 30px;">
244
+ <li>🎯 Takes in information (inputs)</li>
245
+ <li>🤔 Thinks about it (processing)</li>
246
+ <li>💡 Makes a decision (output)</li>
247
+ </ul>
248
+ <p>An AI neural network works the same way! It's like a simplified brain made of math. Let's see it in action!</p>
249
+ </div>
250
+ </div>
251
+
252
+ <div class="mode-content math-mode">
253
+ <div class="math-content">
254
+ <p>A neural network is a function approximator that transforms inputs through layers of neurons:</p>
255
+ <div class="formula">
256
+ f(x) = σ(W₃ · σ(W₂ · σ(W₁ · x + b₁) + b₂) + b₃)
257
+ </div>
258
+ <p>Where:</p>
259
+ <ul style="margin: 15px 0; padding-left: 30px;">
260
+ <li>x = input vector</li>
261
+ <li>Wᵢ = weight matrix for layer i</li>
262
+ <li>bᵢ = bias vector for layer i</li>
263
+ <li>σ = activation function (e.g., ReLU, sigmoid)</li>
264
+ </ul>
265
+ </div>
266
+ </div>
267
+ </div>
268
+
269
+ <div class="section">
270
+ <h2>🎮 Live XOR Training Demo</h2>
271
+ <p>Watch an AI learn the XOR problem in real-time! XOR outputs 1 when inputs are different, 0 when same.</p>
272
+
273
+ <div id="xor-demo">
274
+ <canvas id="network-canvas"></canvas>
275
+
276
+ <div class="controls">
277
+ <button class="control-btn" onclick="startTraining()">▶️ Start Training</button>
278
+ <button class="control-btn" onclick="pauseTraining()">⏸️ Pause</button>
279
+ <button class="control-btn" onclick="resetNetwork()">🔄 Reset</button>
280
+ <button class="control-btn" onclick="stepTraining()">⏭️ Step</button>
281
+ </div>
282
+
283
+ <div class="stats">
284
+ <div class="stat-box">
285
+ <div class="stat-label">Epoch</div>
286
+ <div class="stat-value animated-number" id="epoch">0</div>
287
+ </div>
288
+ <div class="stat-box">
289
+ <div class="stat-label">Loss</div>
290
+ <div class="stat-value animated-number" id="loss">1.000</div>
291
+ </div>
292
+ <div class="stat-box">
293
+ <div class="stat-label">Accuracy</div>
294
+ <div class="stat-value animated-number" id="accuracy">0%</div>
295
+ </div>
296
+ <div class="stat-box">
297
+ <div class="stat-label">Learning Rate</div>
298
+ <div class="stat-value" id="learning-rate">0.1</div>
299
+ </div>
300
+ </div>
301
+
302
+ <canvas id="loss-chart" class="loss-chart"></canvas>
303
+ </div>
304
+ </div>
305
+
306
+ <div class="section">
307
+ <h2>How Does Learning Work?</h2>
308
+
309
+ <div class="mode-content learn-mode active">
310
+ <h3>🎯 Forward Pass: Making Predictions</h3>
311
+ <div class="learn-content">
312
+ <p>The network makes a prediction by passing data forward through each layer:</p>
313
+ <ol style="margin: 15px 0; padding-left: 30px;">
314
+ <li><span class="highlight">Input</span>: Feed in the data (like 0,1 for XOR)</li>
315
+ <li><span class="highlight">Multiply & Add</span>: Each connection has a "strength" (weight)</li>
316
+ <li><span class="highlight">Activate</span>: Decide if the neuron should "fire"</li>
317
+ <li><span class="highlight">Output</span>: Get the final prediction</li>
318
+ </ol>
319
+ </div>
320
+
321
+ <h3>📉 Backward Pass: Learning from Mistakes</h3>
322
+ <div class="learn-content">
323
+ <p>When the network is wrong, it learns by adjusting its connections:</p>
324
+ <ol style="margin: 15px 0; padding-left: 30px;">
325
+ <li><span class="highlight">Calculate Error</span>: How wrong was the prediction?</li>
326
+ <li><span class="highlight">Blame Game</span>: Which connections caused the error?</li>
327
+ <li><span class="highlight">Adjust Weights</span>: Make connections stronger or weaker</li>
328
+ <li><span class="highlight">Repeat</span>: Try again with new weights!</li>
329
+ </ol>
330
+ </div>
331
+ </div>
332
+
333
+ <div class="mode-content math-mode">
334
+ <h3>Forward Propagation</h3>
335
+ <div class="math-content">
336
+ <p>For each layer l:</p>
337
+ <div class="formula">
338
+ z[l] = W[l] · a[l-1] + b[l]
339
+ </div>
340
+ <div class="formula">
341
+ a[l] = σ(z[l])
342
+ </div>
343
+ <p>Where a[0] = x (input) and a[L] = ŷ (output)</p>
344
+ </div>
345
+
346
+ <h3>Backpropagation</h3>
347
+ <div class="math-content">
348
+ <p>Loss function (Mean Squared Error):</p>
349
+ <div class="formula">
350
+ L = ½ Σ(y - ŷ)²
351
+ </div>
352
+ <p>Gradient computation:</p>
353
+ <div class="formula">
354
+ δ[L] = ∇ₐL ⊙ σ'(z[L])
355
+ </div>
356
+ <div class="formula">
357
+ δ[l] = (W[l+1]ᵀ · δ[l+1]) ⊙ σ'(z[l])
358
+ </div>
359
+ <p>Weight update:</p>
360
+ <div class="formula">
361
+ W[l] = W[l] - α · δ[l] · a[l-1]ᵀ
362
+ </div>
363
+ <div class="formula">
364
+ b[l] = b[l] - α · δ[l]
365
+ </div>
366
+ </div>
367
+ </div>
368
+ </div>
369
+
370
+ <div class="section">
371
+ <h2>Key Components Explained</h2>
372
+
373
+ <div class="mode-content learn-mode active">
374
+ <h3>🔗 Weights & Biases</h3>
375
+ <div class="learn-content">
376
+ <p><span class="highlight">Weights</span> are like volume knobs - they control how much each input matters.</p>
377
+ <p><span class="highlight">Biases</span> are like thresholds - they decide when a neuron should activate.</p>
378
+ </div>
379
+
380
+ <h3>⚡ Activation Functions</h3>
381
+ <div class="learn-content">
382
+ <p>These decide if a neuron should "fire" or not:</p>
383
+ <ul style="margin: 15px 0; padding-left: 30px;">
384
+ <li><span class="highlight">ReLU</span>: If positive, pass it on. If negative, block it!</li>
385
+ <li><span class="highlight">Sigmoid</span>: Squash everything between 0 and 1</li>
386
+ <li><span class="highlight">Tanh</span>: Squash everything between -1 and 1</li>
387
+ </ul>
388
+ </div>
389
+
390
+ <h3>🎯 Gradient Descent</h3>
391
+ <div class="learn-content">
392
+ <p>Imagine you're blindfolded on a hill, trying to reach the bottom:</p>
393
+ <ol style="margin: 15px 0; padding-left: 30px;">
394
+ <li>Feel the slope around you (calculate gradient)</li>
395
+ <li>Take a small step downhill (adjust weights)</li>
396
+ <li>Repeat until you reach the bottom (minimum loss)</li>
397
+ </ol>
398
+ </div>
399
+ </div>
400
+
401
+ <div class="mode-content math-mode">
402
+ <h3>Activation Functions</h3>
403
+ <div class="math-content">
404
+ <p><strong>ReLU:</strong></p>
405
+ <div class="formula">
406
+ f(x) = max(0, x)
407
+ </div>
408
+ <div class="formula">
409
+ f'(x) = {1 if x > 0, 0 if x ≤ 0}
410
+ </div>
411
+
412
+ <p><strong>Sigmoid:</strong></p>
413
+ <div class="formula">
414
+ σ(x) = 1 / (1 + e⁻ˣ)
415
+ </div>
416
+ <div class="formula">
417
+ σ'(x) = σ(x) · (1 - σ(x))
418
+ </div>
419
+
420
+ <p><strong>Tanh:</strong></p>
421
+ <div class="formula">
422
+ tanh(x) = (eˣ - e⁻ˣ) / (eˣ + e⁻ˣ)
423
+ </div>
424
+ <div class="formula">
425
+ tanh'(x) = 1 - tanh²(x)
426
+ </div>
427
+ </div>
428
+
429
+ <h3>Gradient Descent Update Rule</h3>
430
+ <div class="math-content">
431
+ <div class="formula">
432
+ θₜ₊₁ = θₜ - α · ∇θ L(θₜ)
433
+ </div>
434
+ <p>Where:</p>
435
+ <ul style="margin: 15px 0; padding-left: 30px;">
436
+ <li>θ = parameters (weights and biases)</li>
437
+ <li>α = learning rate</li>
438
+ <li>∇θ L = gradient of loss with respect to parameters</li>
439
+ </ul>
440
+ </div>
441
+ </div>
442
+ </div>
443
+ </div>
444
+
445
+ <script>
446
+ // Global variables
447
+ let mode = 'learn';
448
+ let network = null;
449
+ let training = false;
450
+ let epoch = 0;
451
+ let lossHistory = [];
452
+ const canvas = document.getElementById('network-canvas');
453
+ const ctx = canvas.getContext('2d');
454
+ const lossCanvas = document.getElementById('loss-chart');
455
+ const lossCtx = lossCanvas.getContext('2d');
456
+ // Set canvas sizes
457
+ function resizeCanvases() {
458
+ canvas.width = canvas.offsetWidth;
459
+ canvas.height = canvas.offsetHeight;
460
+ lossCanvas.width = lossCanvas.offsetWidth;
461
+ lossCanvas.height = lossCanvas.offsetHeight;
462
+ }
463
+ resizeCanvases();
464
+ window.addEventListener('resize', resizeCanvases);
465
+ // Mode switching
466
+ function setMode(newMode) {
467
+ mode = newMode;
468
+ document.querySelectorAll('.mode-btn').forEach(btn => {
469
+ btn.classList.toggle('active', btn.textContent.toLowerCase().includes(newMode));
470
+ });
471
+ document.querySelectorAll('.mode-content').forEach(content => {
472
+ content.classList.toggle('active', content.classList.contains(`${newMode}-mode`));
473
+ });
474
+ }
475
+ // Neural Network Class
476
+ class NeuralNetwork {
477
+ constructor() {
478
+ // Network architecture: 2-25-25-1 (roughly 100 parameters)
479
+ this.layers = [2, 25, 25, 1];
480
+ this.weights = [];
481
+ this.biases = [];
482
+ this.activations = [];
483
+ this.zValues = [];
484
+ this.gradients = [];
485
+ this.learningRate = 0.1;
486
+
487
+ this.initializeNetwork();
488
+ }
489
+ initializeNetwork() {
490
+ // Xavier initialization
491
+ for (let i = 1; i < this.layers.length; i++) {
492
+ const rows = this.layers[i];
493
+ const cols = this.layers[i-1];
494
+ const scale = Math.sqrt(2.0 / cols);
495
+
496
+ // Initialize weights
497
+ this.weights[i-1] = [];
498
+ for (let r = 0; r < rows; r++) {
499
+ this.weights[i-1][r] = [];
500
+ for (let c = 0; c < cols; c++) {
501
+ this.weights[i-1][r][c] = (Math.random() * 2 - 1) * scale;
502
+ }
503
+ }
504
+
505
+ // Initialize biases
506
+ this.biases[i-1] = new Array(rows).fill(0);
507
+ }
508
+ }
509
+ sigmoid(x) {
510
+ return 1 / (1 + Math.exp(-x));
511
+ }
512
+ sigmoidDerivative(x) {
513
+ const s = this.sigmoid(x);
514
+ return s * (1 - s);
515
+ }
516
+ relu(x) {
517
+ return Math.max(0, x);
518
+ }
519
+ reluDerivative(x) {
520
+ return x > 0 ? 1 : 0;
521
+ }
522
+ forward(input) {
523
+ this.activations = [input];
524
+ this.zValues = [];
525
+ for (let i = 0; i < this.weights.length; i++) {
526
+ const z = [];
527
+ const a = [];
528
+
529
+ for (let j = 0; j < this.weights[i].length; j++) {
530
+ let sum = this.biases[i][j];
531
+ for (let k = 0; k < this.weights[i][j].length; k++) {
532
+ sum += this.weights[i][j][k] * this.activations[i][k];
533
+ }
534
+ z.push(sum);
535
+
536
+ // Use ReLU for hidden layers, sigmoid for output
537
+ if (i < this.weights.length - 1) {
538
+ a.push(this.relu(sum));
539
+ } else {
540
+ a.push(this.sigmoid(sum));
541
+ }
542
+ }
543
+
544
+ this.zValues.push(z);
545
+ this.activations.push(a);
546
+ }
547
+ return this.activations[this.activations.length - 1][0];
548
+ }
549
+ backward(input, target) {
550
+ const output = this.forward(input);
551
+ const error = output - target;
552
+
553
+ // Initialize gradients
554
+ this.gradients = [];
555
+
556
+ // Output layer gradients
557
+ let delta = [error * this.sigmoidDerivative(this.zValues[this.zValues.length - 1][0])];
558
+ this.gradients.unshift(delta);
559
+
560
+ // Hidden layer gradients
561
+ for (let i = this.weights.length - 2; i >= 0; i--) {
562
+ const newDelta = [];
563
+ for (let j = 0; j < this.weights[i].length; j++) {
564
+ let sum = 0;
565
+ for (let k = 0; k < delta.length; k++) {
566
+ sum += this.weights[i+1][k][j] * delta[k];
567
+ }
568
+ const activation = i > 0 ?
569
+ this.reluDerivative(this.zValues[i][j]) :
570
+ this.reluDerivative(this.zValues[i][j]);
571
+ newDelta.push(sum * activation);
572
+ }
573
+ delta = newDelta;
574
+ this.gradients.unshift(delta);
575
+ }
576
+ // Update weights and biases
577
+ for (let i = 0; i < this.weights.length; i++) {
578
+ for (let j = 0; j < this.weights[i].length; j++) {
579
+ for (let k = 0; k < this.weights[i][j].length; k++) {
580
+ this.weights[i][j][k] -= this.learningRate * this.gradients[i][j] * this.activations[i][k];
581
+ }
582
+ this.biases[i][j] -= this.learningRate * this.gradients[i][j];
583
+ }
584
+ }
585
+ return error * error;
586
+ }
587
+ train(inputs, targets) {
588
+ let totalLoss = 0;
589
+ for (let i = 0; i < inputs.length; i++) {
590
+ totalLoss += this.backward(inputs[i], targets[i]);
591
+ }
592
+ return totalLoss / inputs.length;
593
+ }
594
+ predict(input) {
595
+ return this.forward(input);
596
+ }
597
+ }
598
+ // XOR training data
599
+ const xorInputs = [[0, 0], [0, 1], [1, 0], [1, 1]];
600
+ const xorTargets = [0, 1, 1, 0];
601
+ // Initialize network
602
+ function resetNetwork() {
603
+ network = new NeuralNetwork();
604
+ epoch = 0;
605
+ lossHistory = [];
606
+ training = false;
607
+ updateStats();
608
+ drawNetwork();
609
+ drawLossChart();
610
+ }
611
+ // Training functions
612
+ function startTraining() {
613
+ training = true;
614
+ trainLoop();
615
+ }
616
+ function pauseTraining() {
617
+ training = false;
618
+ }
619
+ function stepTraining() {
620
+ if (!network) resetNetwork();
621
+ trainStep();
622
+ }
623
+ function trainStep() {
624
+ const loss = network.train(xorInputs, xorTargets);
625
+ epoch++;
626
+ lossHistory.push(loss);
627
+ if (lossHistory.length > 100) lossHistory.shift();
628
+
629
+ updateStats();
630
+ drawNetwork();
631
+ drawLossChart();
632
+ }
633
+ function trainLoop() {
634
+ if (!training) return;
635
+
636
+ trainStep();
637
+
638
+ if (epoch < 1000 && lossHistory[lossHistory.length - 1] > 0.001) {
639
+ requestAnimationFrame(trainLoop);
640
+ } else {
641
+ training = false;
642
+ }
643
+ }
644
+ // Update statistics
645
+ function updateStats() {
646
+ document.getElementById('epoch').textContent = epoch;
647
+
648
+ const loss = lossHistory.length > 0 ? lossHistory[lossHistory.length - 1] : 1;
649
+ document.getElementById('loss').textContent = loss.toFixed(4);
650
+
651
+ // Calculate accuracy
652
+ let correct = 0;
653
+ for (let i = 0; i < xorInputs.length; i++) {
654
+ const prediction = network ? network.predict(xorInputs[i]) : 0.5;
655
+ const rounded = Math.round(prediction);
656
+ if (rounded === xorTargets[i]) correct++;
657
+ }
658
+ const accuracy = (correct / xorInputs.length * 100).toFixed(0);
659
+ document.getElementById('accuracy').textContent = accuracy + '%';
660
+
661
+ // Add pulse animation on high accuracy
662
+ if (accuracy >= 100) {
663
+ document.getElementById('accuracy').parentElement.classList.add('pulse');
664
+ setTimeout(() => {
665
+ document.getElementById('accuracy').parentElement.classList.remove('pulse');
666
+ }, 500);
667
+ }
668
+ }
669
+ // Visualization functions
670
+ function drawNetwork() {
671
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
672
+
673
+ if (!network) return;
674
+
675
+ const layerSpacing = canvas.width / (network.layers.length + 1);
676
+ const neurons = [];
677
+
678
+ // Calculate neuron positions
679
+ for (let i = 0; i < network.layers.length; i++) {
680
+ neurons[i] = [];
681
+ const layerSize = network.layers[i];
682
+ const ySpacing = canvas.height / (layerSize + 1);
683
+
684
+ for (let j = 0; j < layerSize; j++) {
685
+ const x = layerSpacing * (i + 1);
686
+ const y = ySpacing * (j + 1);
687
+ neurons[i].push({ x, y });
688
+ }
689
+ }
690
+
691
+ // Draw connections
692
+ for (let i = 0; i < network.weights.length; i++) {
693
+ for (let j = 0; j < network.weights[i].length; j++) {
694
+ for (let k = 0; k < network.weights[i][j].length; k++) {
695
+ const weight = network.weights[i][j][k];
696
+ const opacity = Math.min(Math.abs(weight) / 2, 1);
697
+
698
+ ctx.beginPath();
699
+ ctx.moveTo(neurons[i][k].x, neurons[i][k].y);
700
+ ctx.lineTo(neurons[i+1][j].x, neurons[i+1][j].y);
701
+
702
+ if (weight > 0) {
703
+ ctx.strokeStyle = `rgba(76, 175, 80, ${opacity})`;
704
+ } else {
705
+ ctx.strokeStyle = `rgba(244, 67, 54, ${opacity})`;
706
+ }
707
+
708
+ ctx.lineWidth = Math.abs(weight) * 2;
709
+ ctx.stroke();
710
+ }
711
+ }
712
+ }
713
+
714
+ // Draw neurons
715
+ for (let i = 0; i < neurons.length; i++) {
716
+ for (let j = 0; j < neurons[i].length; j++) {
717
+ const neuron = neurons[i][j];
718
+
719
+ // Get activation value
720
+ let activation = 0;
721
+ if (network.activations[i] && network.activations[i][j] !== undefined) {
722
+ activation = network.activations[i][j];
723
+ }
724
+
725
+ const intensity = Math.min(activation * 255, 255);
726
+
727
+ ctx.beginPath();
728
+ ctx.arc(neuron.x, neuron.y, 15, 0, Math.PI * 2);
729
+ ctx.fillStyle = `rgb(${intensity}, ${intensity}, ${255})`;
730
+ ctx.fill();
731
+ ctx.strokeStyle = '#4CAF50';
732
+ ctx.lineWidth = 2;
733
+ ctx.stroke();
734
+
735
+ // Draw activation value for visible neurons
736
+ if (network.layers[i] <= 5 || i === 0 || i === network.layers.length - 1) {
737
+ ctx.fillStyle = '#fff';
738
+ ctx.font = '10px Arial';
739
+ ctx.textAlign = 'center';
740
+ ctx.textBaseline = 'middle';
741
+ ctx.fillText(activation.toFixed(2), neuron.x, neuron.y);
742
+ }
743
+ }
744
+ }
745
+
746
+ // Draw layer labels
747
+ ctx.fillStyle = '#888';
748
+ ctx.font = '14px Arial';
749
+ ctx.textAlign = 'center';
750
+
751
+ const labels = ['Input', 'Hidden 1', 'Hidden 2', 'Output'];
752
+ for (let i = 0; i < network.layers.length; i++) {
753
+ const x = layerSpacing * (i + 1);
754
+ ctx.fillText(labels[i], x, 30);
755
+ ctx.fillText(`(${network.layers[i]} neurons)`, x, 45);
756
+ }
757
+
758
+ // Draw XOR truth table
759
+ ctx.fillStyle = '#4CAF50';
760
+ ctx.font = '12px Arial';
761
+ ctx.textAlign = 'left';
762
+ ctx.fillText('XOR Truth Table:', 20, canvas.height - 80);
763
+ ctx.fillStyle = '#888';
764
+ ctx.fillText('0 XOR 0 = 0', 20, canvas.height - 60);
765
+ ctx.fillText('0 XOR 1 = 1', 20, canvas.height - 45);
766
+ ctx.fillText('1 XOR 0 = 1', 20, canvas.height - 30);
767
+ ctx.fillText('1 XOR 1 = 0', 20, canvas.height - 15);
768
+
769
+ // Show current predictions
770
+ if (network) {
771
+ ctx.fillStyle = '#4CAF50';
772
+ ctx.fillText('Network Output:', 150, canvas.height - 80);
773
+ ctx.fillStyle = '#888';
774
+ for (let i = 0; i < xorInputs.length; i++) {
775
+ const prediction = network.predict(xorInputs[i]);
776
+ const text = `${xorInputs[i][0]} XOR ${xorInputs[i][1]} = ${prediction.toFixed(3)}`;
777
+ ctx.fillText(text, 150, canvas.height - 60 + i * 15);
778
+ }
779
+ }
780
+ }
781
+ function drawLossChart() {
782
+ lossCtx.clearRect(0, 0, lossCanvas.width, lossCanvas.height);
783
+
784
+ if (lossHistory.length < 2) return;
785
+
786
+ // Find min and max for scaling
787
+ const maxLoss = Math.max(...lossHistory, 0.5);
788
+ const minLoss = 0;
789
+
790
+ // Draw axes
791
+ lossCtx.strokeStyle = '#444';
792
+ lossCtx.lineWidth = 1;
793
+ lossCtx.beginPath();
794
+ lossCtx.moveTo(40, 10);
795
+ lossCtx.lineTo(40, lossCanvas.height - 30);
796
+ lossCtx.lineTo(lossCanvas.width - 10, lossCanvas.height - 30);
797
+ lossCtx.stroke();
798
+
799
+ // Draw labels
800
+ lossCtx.fillStyle = '#888';
801
+ lossCtx.font = '12px Arial';
802
+ lossCtx.textAlign = 'right';
803
+ lossCtx.fillText(maxLoss.toFixed(3), 35, 15);
804
+ lossCtx.fillText('0', 35, lossCanvas.height - 30);
805
+ lossCtx.textAlign = 'center';
806
+ lossCtx.fillText('Loss over Time', lossCanvas.width / 2, lossCanvas.height - 10);
807
+
808
+ // Draw loss curve
809
+ lossCtx.strokeStyle = '#4CAF50';
810
+ lossCtx.lineWidth = 2;
811
+ lossCtx.beginPath();
812
+
813
+ const xStep = (lossCanvas.width - 50) / (lossHistory.length - 1);
814
+ const yScale = (lossCanvas.height - 50) / (maxLoss - minLoss);
815
+
816
+ for (let i = 0; i < lossHistory.length; i++) {
817
+ const x = 40 + i * xStep;
818
+ const y = lossCanvas.height - 30 - (lossHistory[i] - minLoss) * yScale;
819
+
820
+ if (i === 0) {
821
+ lossCtx.moveTo(x, y);
822
+ } else {
823
+ lossCtx.lineTo(x, y);
824
+ }
825
+ }
826
+
827
+ lossCtx.stroke();
828
+
829
+ // Draw current loss point
830
+ if (lossHistory.length > 0) {
831
+ const lastX = 40 + (lossHistory.length - 1) * xStep;
832
+ const lastY = lossCanvas.height - 30 - (lossHistory[lossHistory.length - 1] - minLoss) * yScale;
833
+
834
+ lossCtx.beginPath();
835
+ lossCtx.arc(lastX, lastY, 4, 0, Math.PI * 2);
836
+ lossCtx.fillStyle = '#4CAF50';
837
+ lossCtx.fill();
838
+ }
839
+ }
840
+ // Initialize
841
+ resetNetwork();
842
+ </script>
843
+ </body>
844
+ </html>