autograd-ts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +289 -0
- package/dist/core/Value.d.ts +88 -0
- package/dist/core/Value.d.ts.map +1 -0
- package/dist/core/Value.js +167 -0
- package/dist/core/Value.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/nn/Layer.d.ts +27 -0
- package/dist/nn/Layer.d.ts.map +1 -0
- package/dist/nn/Layer.js +35 -0
- package/dist/nn/Layer.js.map +1 -0
- package/dist/nn/MLP.d.ts +37 -0
- package/dist/nn/MLP.d.ts.map +1 -0
- package/dist/nn/MLP.js +61 -0
- package/dist/nn/MLP.js.map +1 -0
- package/dist/nn/Neuron.d.ts +31 -0
- package/dist/nn/Neuron.d.ts.map +1 -0
- package/dist/nn/Neuron.js +50 -0
- package/dist/nn/Neuron.js.map +1 -0
- package/dist/nn/index.d.ts +6 -0
- package/dist/nn/index.d.ts.map +1 -0
- package/dist/nn/index.js +13 -0
- package/dist/nn/index.js.map +1 -0
- package/dist/nn/loss.d.ts +9 -0
- package/dist/nn/loss.d.ts.map +1 -0
- package/dist/nn/loss.js +22 -0
- package/dist/nn/loss.js.map +1 -0
- package/dist/nn/optim.d.ts +8 -0
- package/dist/nn/optim.d.ts.map +1 -0
- package/dist/nn/optim.js +14 -0
- package/dist/nn/optim.js.map +1 -0
- package/package.json +35 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eyas Ranjous
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# autograd-ts
|
|
2
|
+
|
|
3
|
+
A tiny Typescript library that implements **reverse-mode automatic differentiation** (autograd) and neural network training.
|
|
4
|
+
|
|
5
|
+
The goal of the project is exploring the fundamental mechanism that allows neural networks to learn.
|
|
6
|
+
|
|
7
|
+
At its core, a neural network is a system of interconnected computations.
|
|
8
|
+
|
|
9
|
+
Producing an output is straightforward. However, learning requires determining how each value influenced that output and how those values should be adjusted when the prediction is wrong.
|
|
10
|
+
|
|
11
|
+
This library explores the mechanism that makes that possible.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Understanding Learning
|
|
16
|
+
|
|
17
|
+
A neural network can make a prediction by evaluating a series of mathematical operations.
|
|
18
|
+
|
|
19
|
+
For example, consider the simplified model:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
z = x * y + x
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Here, x and y are inputs to the model and z is the resulting prediction.
|
|
26
|
+
|
|
27
|
+
Given the inputs:
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
x = 2
|
|
31
|
+
y = 3
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
the model produces:
|
|
35
|
+
```
|
|
36
|
+
z = 8
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Suppose the expected value was:
|
|
40
|
+
|
|
41
|
+
```text
|
|
42
|
+
target = 10
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Now we need to answer:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
1. Which values contributed to the error?
|
|
49
|
+
2. How much did they contribute?
|
|
50
|
+
3. How should they change?
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For a simple expression this may seem manageable. For a neural network containing thousands or millions of parameters, it becomes a much more difficult problem.
|
|
54
|
+
|
|
55
|
+
This leads to the central question behind the project:
|
|
56
|
+
|
|
57
|
+
> When a neural network makes a prediction, how does it know which weights to adjust?
|
|
58
|
+
|
|
59
|
+
A model must be able to trace a prediction back through the computations that produced it, measure how each value contributed to the final result, and determine how those values should change when the prediction is wrong.
|
|
60
|
+
|
|
61
|
+
Modern machine learning systems solve this problem through a sequence of concepts that build on one another:
|
|
62
|
+
|
|
63
|
+
```text
|
|
64
|
+
Computation Graph
|
|
65
|
+
↓
|
|
66
|
+
Automatic Differentiation
|
|
67
|
+
↓
|
|
68
|
+
Backpropagation
|
|
69
|
+
↓
|
|
70
|
+
Gradient Descent
|
|
71
|
+
↓
|
|
72
|
+
Learning
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
# Layer 1: Computation Graphs
|
|
78
|
+
|
|
79
|
+
Everything begins with mathematical expressions.
|
|
80
|
+
|
|
81
|
+
Consider:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
z = x * y + x
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Expanded:
|
|
88
|
+
|
|
89
|
+
```text
|
|
90
|
+
a = x * y
|
|
91
|
+
z = a + x
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
This expression can be represented as a directed acyclic graph (DAG):
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
x -----------\
|
|
98
|
+
* ---> a ----\
|
|
99
|
+
y -----------/ \
|
|
100
|
+
+ ---> z
|
|
101
|
+
x -------------------------/
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Each node represents a computed value.
|
|
105
|
+
|
|
106
|
+
| Node | Meaning | Value |
|
|
107
|
+
| ---- | ------- | ----- |
|
|
108
|
+
| x | Input | 2 |
|
|
109
|
+
| y | Input | 3 |
|
|
110
|
+
| a | x * y | 6 |
|
|
111
|
+
| z | a + x | 8 |
|
|
112
|
+
|
|
113
|
+
Each edge represents a dependency relationship.
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
x → a
|
|
117
|
+
y → a
|
|
118
|
+
a → z
|
|
119
|
+
x → z
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The graph gives us a structured representation of the computation.
|
|
123
|
+
|
|
124
|
+
Once that structure exists, we can begin reasoning about how changes in one value affect others.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
# Layer 2: Automatic Differentiation
|
|
129
|
+
|
|
130
|
+
As we have the computation graph, we can now ask:
|
|
131
|
+
|
|
132
|
+
> How much did each node contribute to the final output?
|
|
133
|
+
|
|
134
|
+
For the expression:
|
|
135
|
+
|
|
136
|
+
```text
|
|
137
|
+
z = x * y + x
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
we want:
|
|
141
|
+
|
|
142
|
+
```text
|
|
143
|
+
∂z/∂x
|
|
144
|
+
∂z/∂y
|
|
145
|
+
```
|
|
146
|
+
(∂ denotes a partial derivative).
|
|
147
|
+
|
|
148
|
+
The autograd engine computes these derivatives automatically using reverse graph traversal and the chain rule.
|
|
149
|
+
|
|
150
|
+
So after backpropagation they become:
|
|
151
|
+
|
|
152
|
+
```text
|
|
153
|
+
x.grad = 4
|
|
154
|
+
y.grad = 2
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
These gradients measure how sensitive the final output is to each input.
|
|
158
|
+
|
|
159
|
+
For example:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
∂z/∂x = 4
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
which means that a small increase of 1 in x would increase z by approximately 4.
|
|
166
|
+
|
|
167
|
+
This process is known as **reverse-mode automatic differentiation**, the same technique used by modern machine learning frameworks.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
# Layer 3: Neural Networks
|
|
172
|
+
|
|
173
|
+
Neural networks are built directly on top of the computation graph.
|
|
174
|
+
|
|
175
|
+
A single neuron computes:
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
w1*x1 + w2*x2 + b
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
which is simply a larger graph.
|
|
182
|
+
|
|
183
|
+
```text
|
|
184
|
+
x1 --*
|
|
185
|
+
|
|
|
186
|
+
w1 --|
|
|
187
|
+
|
|
188
|
+
x2 --*
|
|
189
|
+
+ ---> tanh ---> output
|
|
190
|
+
w2 --|
|
|
191
|
+
|
|
192
|
+
b -------------|
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The weights (`w1`, `w2`) and bias (`b`) are themselves graph nodes.
|
|
196
|
+
|
|
197
|
+
The autograd engine computes gradients for those weights automatically.
|
|
198
|
+
|
|
199
|
+
Nothing special is added for neural networks, the same graph and differentiation system powers everything.
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
# Layer 4: Learning
|
|
204
|
+
|
|
205
|
+
Once gradients are available, training becomes possible.
|
|
206
|
+
|
|
207
|
+
A typical training loop looks like:
|
|
208
|
+
|
|
209
|
+
```text
|
|
210
|
+
Forward Pass
|
|
211
|
+
↓
|
|
212
|
+
Compute Loss
|
|
213
|
+
↓
|
|
214
|
+
Backward Pass
|
|
215
|
+
↓
|
|
216
|
+
Update Weights
|
|
217
|
+
↓
|
|
218
|
+
Repeat
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Over time the network adjusts its weights to reduce prediction error.
|
|
222
|
+
|
|
223
|
+
This feedback loop is the mechanism that allows neural networks to learn.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
# Project Scope
|
|
228
|
+
|
|
229
|
+
Version 0.1.0 focuses on a minimal learning system.
|
|
230
|
+
|
|
231
|
+
## Core Autograd Engine
|
|
232
|
+
|
|
233
|
+
* Value
|
|
234
|
+
* add
|
|
235
|
+
* sub
|
|
236
|
+
* mul
|
|
237
|
+
* div
|
|
238
|
+
* pow
|
|
239
|
+
* tanh
|
|
240
|
+
* relu
|
|
241
|
+
* exp
|
|
242
|
+
* backward
|
|
243
|
+
|
|
244
|
+
## Neural Network Components
|
|
245
|
+
|
|
246
|
+
* Neuron
|
|
247
|
+
* Layer
|
|
248
|
+
* MLP (Multi-Layer Perceptron)
|
|
249
|
+
|
|
250
|
+
## Training Utilities
|
|
251
|
+
|
|
252
|
+
* Mean Squared Error (MSE)
|
|
253
|
+
* Stochastic Gradient Descent (SGD)
|
|
254
|
+
|
|
255
|
+
## Examples
|
|
256
|
+
```
|
|
257
|
+
examples/
|
|
258
|
+
├── basic.ts
|
|
259
|
+
└── xor.ts
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Basic computation graph example**
|
|
263
|
+
```
|
|
264
|
+
z: 8
|
|
265
|
+
dz/dx: 4
|
|
266
|
+
dz/dy: 2
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
**XOR training example**
|
|
270
|
+
```
|
|
271
|
+
XOR Training
|
|
272
|
+
epoch=0 loss=1.824531
|
|
273
|
+
epoch=100 loss=0.712943
|
|
274
|
+
epoch=200 loss=0.403817
|
|
275
|
+
epoch=300 loss=0.182691
|
|
276
|
+
epoch=400 loss=0.087432
|
|
277
|
+
epoch=500 loss=0.041827
|
|
278
|
+
epoch=600 loss=0.021554
|
|
279
|
+
epoch=700 loss=0.012115
|
|
280
|
+
epoch=800 loss=0.007083
|
|
281
|
+
epoch=900 loss=0.004291
|
|
282
|
+
|
|
283
|
+
XOR Predictions
|
|
284
|
+
[0, 0] => 0.0213
|
|
285
|
+
[0, 1] => 0.9834
|
|
286
|
+
[1, 0] => 0.9772
|
|
287
|
+
[1, 1] => 0.0189
|
|
288
|
+
```
|
|
289
|
+
---
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export type BackwardFn = () => void;
|
|
2
|
+
interface ValueOptions {
|
|
3
|
+
prev?: Value[];
|
|
4
|
+
op?: string;
|
|
5
|
+
backward?: BackwardFn;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Scalar node in a computation graph supporting reverse-mode automatic differentiation.
|
|
9
|
+
*/
|
|
10
|
+
export declare class Value {
|
|
11
|
+
data: number;
|
|
12
|
+
grad: number;
|
|
13
|
+
private _prev;
|
|
14
|
+
private _op?;
|
|
15
|
+
private _backward;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new computation graph node.
|
|
18
|
+
* @param data Numeric value stored in this node.
|
|
19
|
+
* @param opts Internal metadata for graph construction.
|
|
20
|
+
*/
|
|
21
|
+
constructor(data: number, opts?: ValueOptions);
|
|
22
|
+
/**
|
|
23
|
+
* Adds another value to this value.
|
|
24
|
+
* @param v Value or number to add.
|
|
25
|
+
* @returns New Value representing the sum.
|
|
26
|
+
*/
|
|
27
|
+
add(v: Value | number): Value;
|
|
28
|
+
/**
|
|
29
|
+
* Multiplies this value by another.
|
|
30
|
+
* @param v Value or number to multiply.
|
|
31
|
+
* @returns New Value representing the product.
|
|
32
|
+
*/
|
|
33
|
+
mul(v: Value | number): Value;
|
|
34
|
+
/**
|
|
35
|
+
* Raises this value to a numeric power.
|
|
36
|
+
* @param n Exponent.
|
|
37
|
+
* @returns New Value representing x^n.
|
|
38
|
+
*/
|
|
39
|
+
pow(n: number): Value;
|
|
40
|
+
/**
|
|
41
|
+
* Applies the hyperbolic tangent activation.
|
|
42
|
+
* @returns New Value representing tanh(x).
|
|
43
|
+
*/
|
|
44
|
+
tanh(): Value;
|
|
45
|
+
/**
|
|
46
|
+
* Applies the ReLU activation function.
|
|
47
|
+
* @returns New Value representing max(0, x).
|
|
48
|
+
*/
|
|
49
|
+
relu(): Value;
|
|
50
|
+
/**
|
|
51
|
+
* Negates this value.
|
|
52
|
+
* @returns New Value representing -x.
|
|
53
|
+
*/
|
|
54
|
+
neg(): Value;
|
|
55
|
+
/**
|
|
56
|
+
* Subtracts another value from this value.
|
|
57
|
+
* @param v Value or number to subtract.
|
|
58
|
+
* @returns New Value representing x - y.
|
|
59
|
+
*/
|
|
60
|
+
sub(v: Value | number): Value;
|
|
61
|
+
/**
|
|
62
|
+
* Divides this value by another.
|
|
63
|
+
* @param v Value or number to divide by.
|
|
64
|
+
* @returns New Value representing x / y.
|
|
65
|
+
*/
|
|
66
|
+
div(v: Value | number): Value;
|
|
67
|
+
/**
|
|
68
|
+
* Resets the gradient stored on this node.
|
|
69
|
+
*/
|
|
70
|
+
zeroGrad(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Performs reverse-mode automatic differentiation to compute gradients.
|
|
73
|
+
*/
|
|
74
|
+
backward(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Returns a human-readable representation of the Value.
|
|
77
|
+
* @returns String representation of this node.
|
|
78
|
+
*/
|
|
79
|
+
toString(): string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A helper for creating a Value from a number.
|
|
83
|
+
* @param n Numeric value.
|
|
84
|
+
* @returns Value
|
|
85
|
+
*/
|
|
86
|
+
export declare function val(n: number): Value;
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=Value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Value.d.ts","sourceRoot":"","sources":["../../src/core/Value.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC;AAEpC,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,UAAU,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,KAAK;IACT,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,SAAK;IAEhB,OAAO,CAAC,KAAK,CAAU;IACvB,OAAO,CAAC,GAAG,CAAC,CAAS;IACrB,OAAO,CAAC,SAAS,CAAa;IAE9B;;;;OAIG;gBACS,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY;IAO7C;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK;IAepC;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK;IAepC;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK;IAY5B;;;OAGG;IACI,IAAI,IAAI,KAAK;IAcpB;;;OAGG;IACI,IAAI,IAAI,KAAK;IAYpB;;;OAGG;IACI,GAAG,IAAI,KAAK;IAInB;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK;IAIpC;;;;OAIG;IACI,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK;IAKpC;;OAEG;IACI,QAAQ,IAAI,IAAI;IAIvB;;OAEG;IACI,QAAQ,IAAI,IAAI;IAyBvB;;;OAGG;IACI,QAAQ,IAAI,MAAM;CAG1B;AAED;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,KAAK,CAEpC"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Value = void 0;
|
|
4
|
+
exports.val = val;
|
|
5
|
+
/**
|
|
6
|
+
* Scalar node in a computation graph supporting reverse-mode automatic differentiation.
|
|
7
|
+
*/
|
|
8
|
+
class Value {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new computation graph node.
|
|
11
|
+
* @param data Numeric value stored in this node.
|
|
12
|
+
* @param opts Internal metadata for graph construction.
|
|
13
|
+
*/
|
|
14
|
+
constructor(data, opts) {
|
|
15
|
+
this.grad = 0;
|
|
16
|
+
this.data = data;
|
|
17
|
+
this._prev = opts?.prev ?? [];
|
|
18
|
+
this._op = opts?.op;
|
|
19
|
+
this._backward = opts?.backward ?? (() => { });
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Adds another value to this value.
|
|
23
|
+
* @param v Value or number to add.
|
|
24
|
+
* @returns New Value representing the sum.
|
|
25
|
+
*/
|
|
26
|
+
add(v) {
|
|
27
|
+
const o = v instanceof Value ? v : val(v);
|
|
28
|
+
const out = new Value(this.data + o.data, {
|
|
29
|
+
prev: [this, o],
|
|
30
|
+
op: '+',
|
|
31
|
+
backward: () => {
|
|
32
|
+
this.grad += out.grad;
|
|
33
|
+
o.grad += out.grad;
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
return out;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Multiplies this value by another.
|
|
40
|
+
* @param v Value or number to multiply.
|
|
41
|
+
* @returns New Value representing the product.
|
|
42
|
+
*/
|
|
43
|
+
mul(v) {
|
|
44
|
+
const o = v instanceof Value ? v : val(v);
|
|
45
|
+
const out = new Value(this.data * o.data, {
|
|
46
|
+
prev: [this, o],
|
|
47
|
+
op: '*',
|
|
48
|
+
backward: () => {
|
|
49
|
+
this.grad += o.data * out.grad;
|
|
50
|
+
o.grad += this.data * out.grad;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Raises this value to a numeric power.
|
|
57
|
+
* @param n Exponent.
|
|
58
|
+
* @returns New Value representing x^n.
|
|
59
|
+
*/
|
|
60
|
+
pow(n) {
|
|
61
|
+
const out = new Value(this.data ** n, {
|
|
62
|
+
prev: [this],
|
|
63
|
+
op: `pow(${n})`,
|
|
64
|
+
backward: () => {
|
|
65
|
+
this.grad += n * this.data ** (n - 1) * out.grad;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Applies the hyperbolic tangent activation.
|
|
72
|
+
* @returns New Value representing tanh(x).
|
|
73
|
+
*/
|
|
74
|
+
tanh() {
|
|
75
|
+
const t = Math.tanh(this.data);
|
|
76
|
+
const out = new Value(t, {
|
|
77
|
+
prev: [this],
|
|
78
|
+
op: 'tanh',
|
|
79
|
+
backward: () => {
|
|
80
|
+
this.grad += (1 - t * t) * out.grad;
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Applies the ReLU activation function.
|
|
87
|
+
* @returns New Value representing max(0, x).
|
|
88
|
+
*/
|
|
89
|
+
relu() {
|
|
90
|
+
const out = new Value(this.data > 0 ? this.data : 0, {
|
|
91
|
+
prev: [this],
|
|
92
|
+
op: 'relu',
|
|
93
|
+
backward: () => {
|
|
94
|
+
this.grad += (this.data > 0 ? 1 : 0) * out.grad;
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Negates this value.
|
|
101
|
+
* @returns New Value representing -x.
|
|
102
|
+
*/
|
|
103
|
+
neg() {
|
|
104
|
+
return this.mul(-1);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Subtracts another value from this value.
|
|
108
|
+
* @param v Value or number to subtract.
|
|
109
|
+
* @returns New Value representing x - y.
|
|
110
|
+
*/
|
|
111
|
+
sub(v) {
|
|
112
|
+
return this.add(v instanceof Value ? v.neg() : -v);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Divides this value by another.
|
|
116
|
+
* @param v Value or number to divide by.
|
|
117
|
+
* @returns New Value representing x / y.
|
|
118
|
+
*/
|
|
119
|
+
div(v) {
|
|
120
|
+
const o = v instanceof Value ? v : val(v);
|
|
121
|
+
return this.mul(o.pow(-1));
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Resets the gradient stored on this node.
|
|
125
|
+
*/
|
|
126
|
+
zeroGrad() {
|
|
127
|
+
this.grad = 0;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Performs reverse-mode automatic differentiation to compute gradients.
|
|
131
|
+
*/
|
|
132
|
+
backward() {
|
|
133
|
+
const topo = [];
|
|
134
|
+
const visited = new Set();
|
|
135
|
+
const buildTopo = (v) => {
|
|
136
|
+
if (visited.has(v))
|
|
137
|
+
return;
|
|
138
|
+
visited.add(v);
|
|
139
|
+
for (const parent of v._prev) {
|
|
140
|
+
buildTopo(parent);
|
|
141
|
+
}
|
|
142
|
+
topo.push(v);
|
|
143
|
+
};
|
|
144
|
+
buildTopo(this);
|
|
145
|
+
this.grad = 1;
|
|
146
|
+
for (let i = topo.length - 1; i >= 0; i--) {
|
|
147
|
+
topo[i]._backward();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Returns a human-readable representation of the Value.
|
|
152
|
+
* @returns String representation of this node.
|
|
153
|
+
*/
|
|
154
|
+
toString() {
|
|
155
|
+
return `Value(data=${this.data}, grad=${this.grad})`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
exports.Value = Value;
|
|
159
|
+
/**
|
|
160
|
+
* A helper for creating a Value from a number.
|
|
161
|
+
* @param n Numeric value.
|
|
162
|
+
* @returns Value
|
|
163
|
+
*/
|
|
164
|
+
function val(n) {
|
|
165
|
+
return new Value(n);
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=Value.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Value.js","sourceRoot":"","sources":["../../src/core/Value.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.val = exports.Value = void 0;
|
|
4
|
+
var Value_1 = require("./core/Value");
|
|
5
|
+
Object.defineProperty(exports, "Value", { enumerable: true, get: function () { return Value_1.Value; } });
|
|
6
|
+
Object.defineProperty(exports, "val", { enumerable: true, get: function () { return Value_1.val; } });
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,sCAA0C;AAAjC,8FAAA,KAAK,OAAA;AAAE,4FAAA,GAAG,OAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Value } from '../core/Value';
|
|
2
|
+
import { Activation } from './Neuron';
|
|
3
|
+
/**
|
|
4
|
+
* Fully connected layer containing multiple neurons.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Layer {
|
|
7
|
+
private neurons;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a layer of neurons.
|
|
10
|
+
* @param inputSize Number of inputs per neuron.
|
|
11
|
+
* @param outputSize Number of neurons in the layer.
|
|
12
|
+
* @param activation Activation function used by each neuron.
|
|
13
|
+
*/
|
|
14
|
+
constructor(inputSize: number, outputSize: number, activation?: Activation);
|
|
15
|
+
/**
|
|
16
|
+
* Computes outputs for all neurons in the layer.
|
|
17
|
+
* @param inputs Input values.
|
|
18
|
+
* @returns Layer outputs.
|
|
19
|
+
*/
|
|
20
|
+
forward(inputs: Value[]): Value[];
|
|
21
|
+
/**
|
|
22
|
+
* Returns all trainable parameters in the layer.
|
|
23
|
+
* @returns Flattened list of neuron parameters.
|
|
24
|
+
*/
|
|
25
|
+
parameters(): Value[];
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=Layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Layer.d.ts","sourceRoot":"","sources":["../../src/nn/Layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,UAAU,EAAU,MAAM,UAAU,CAAC;AAE9C;;GAEG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,OAAO,CAAW;IAE1B;;;;;OAKG;gBACS,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,GAAE,UAAmB;IAOlF;;;;OAIG;IACI,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE;IAIxC;;;OAGG;IACI,UAAU,IAAI,KAAK,EAAE;CAG7B"}
|
package/dist/nn/Layer.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Layer = void 0;
|
|
4
|
+
const Neuron_1 = require("./Neuron");
|
|
5
|
+
/**
|
|
6
|
+
* Fully connected layer containing multiple neurons.
|
|
7
|
+
*/
|
|
8
|
+
class Layer {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a layer of neurons.
|
|
11
|
+
* @param inputSize Number of inputs per neuron.
|
|
12
|
+
* @param outputSize Number of neurons in the layer.
|
|
13
|
+
* @param activation Activation function used by each neuron.
|
|
14
|
+
*/
|
|
15
|
+
constructor(inputSize, outputSize, activation = "tanh") {
|
|
16
|
+
this.neurons = Array.from({ length: outputSize }, () => new Neuron_1.Neuron(inputSize, activation));
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Computes outputs for all neurons in the layer.
|
|
20
|
+
* @param inputs Input values.
|
|
21
|
+
* @returns Layer outputs.
|
|
22
|
+
*/
|
|
23
|
+
forward(inputs) {
|
|
24
|
+
return this.neurons.map((neuron) => neuron.forward(inputs));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns all trainable parameters in the layer.
|
|
28
|
+
* @returns Flattened list of neuron parameters.
|
|
29
|
+
*/
|
|
30
|
+
parameters() {
|
|
31
|
+
return this.neurons.flatMap((neuron) => neuron.parameters());
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.Layer = Layer;
|
|
35
|
+
//# sourceMappingURL=Layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Layer.js","sourceRoot":"","sources":["../../src/nn/Layer.ts"],"names":[],"mappings":";;;AACA,qCAA8C;AAE9C;;GAEG;AACH,MAAa,KAAK;IAGhB;;;;;OAKG;IACH,YAAY,SAAiB,EAAE,UAAkB,EAAE,aAAyB,MAAM;QAChF,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CACvB,EAAE,MAAM,EAAE,UAAU,EAAE,EACtB,GAAG,EAAE,CAAC,IAAI,eAAM,CAAC,SAAS,EAAE,UAAU,CAAC,CACxC,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,MAAe;QAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,CAAC;IAED;;;OAGG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAC/D,CAAC;CACF;AAhCD,sBAgCC"}
|
package/dist/nn/MLP.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Value } from '../core/Value';
|
|
2
|
+
import { Activation } from './Neuron';
|
|
3
|
+
/**
|
|
4
|
+
* Multi-layer perceptron composed of one or more fully connected layers.
|
|
5
|
+
*/
|
|
6
|
+
export declare class MLP {
|
|
7
|
+
private layers;
|
|
8
|
+
/**
|
|
9
|
+
* Creates a multi-layer perceptron.
|
|
10
|
+
* @param inputSize Number of input features.
|
|
11
|
+
* @param layerSizes Output size of each layer.
|
|
12
|
+
* @param options Network activation configuration.
|
|
13
|
+
*/
|
|
14
|
+
constructor(inputSize: number, layerSizes: number[], options?: {
|
|
15
|
+
hiddenActivation?: Activation;
|
|
16
|
+
outputActivation?: Activation;
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Runs a forward pass through the network.
|
|
20
|
+
* @param inputs Input feature values.
|
|
21
|
+
* @returns Network predictions.
|
|
22
|
+
*/
|
|
23
|
+
forward(inputs: number[]): Value[];
|
|
24
|
+
/**
|
|
25
|
+
* Runs a forward pass through the network.
|
|
26
|
+
* @param inputs Input feature values.
|
|
27
|
+
* @returns Network predictions.
|
|
28
|
+
*/
|
|
29
|
+
parameters(): Value[];
|
|
30
|
+
/**
|
|
31
|
+
* Runs a forward pass through the network.
|
|
32
|
+
* @param inputs Input feature values.
|
|
33
|
+
* @returns Network predictions.
|
|
34
|
+
*/
|
|
35
|
+
zeroGrad(): void;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=MLP.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MLP.d.ts","sourceRoot":"","sources":["../../src/nn/MLP.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAO,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC;;GAEG;AACH,qBAAa,GAAG;IACd,OAAO,CAAC,MAAM,CAAU;IAExB;;;;;OAKG;gBAED,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,OAAO,CAAC,EAAE;QACR,gBAAgB,CAAC,EAAE,UAAU,CAAC;QAC9B,gBAAgB,CAAC,EAAE,UAAU,CAAC;KAC/B;IA0BH;;;;OAIG;IACI,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,EAAE;IAUzC;;;;OAIG;IACI,UAAU,IAAI,KAAK,EAAE;IAI5B;;;;OAIG;IACI,QAAQ,IAAI,IAAI;CAKxB"}
|
package/dist/nn/MLP.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MLP = void 0;
|
|
4
|
+
const Value_1 = require("../core/Value");
|
|
5
|
+
const Layer_1 = require("./Layer");
|
|
6
|
+
/**
|
|
7
|
+
* Multi-layer perceptron composed of one or more fully connected layers.
|
|
8
|
+
*/
|
|
9
|
+
class MLP {
|
|
10
|
+
/**
|
|
11
|
+
* Creates a multi-layer perceptron.
|
|
12
|
+
* @param inputSize Number of input features.
|
|
13
|
+
* @param layerSizes Output size of each layer.
|
|
14
|
+
* @param options Network activation configuration.
|
|
15
|
+
*/
|
|
16
|
+
constructor(inputSize, layerSizes, options) {
|
|
17
|
+
if (layerSizes.length === 0) {
|
|
18
|
+
throw new Error('MLP must have at least one layer');
|
|
19
|
+
}
|
|
20
|
+
const hiddenActivation = options?.hiddenActivation ?? 'tanh';
|
|
21
|
+
const outputActivation = options?.outputActivation ?? 'none';
|
|
22
|
+
const sizes = [inputSize, ...layerSizes];
|
|
23
|
+
this.layers = [];
|
|
24
|
+
for (let i = 0; i < layerSizes.length; i++) {
|
|
25
|
+
const isOutputLayer = i === layerSizes.length - 1;
|
|
26
|
+
this.layers.push(new Layer_1.Layer(sizes[i], sizes[i + 1], isOutputLayer ? outputActivation : hiddenActivation));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Runs a forward pass through the network.
|
|
31
|
+
* @param inputs Input feature values.
|
|
32
|
+
* @returns Network predictions.
|
|
33
|
+
*/
|
|
34
|
+
forward(inputs) {
|
|
35
|
+
let output = inputs.map((input) => (0, Value_1.val)(input));
|
|
36
|
+
for (const layer of this.layers) {
|
|
37
|
+
output = layer.forward(output);
|
|
38
|
+
}
|
|
39
|
+
return output;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Runs a forward pass through the network.
|
|
43
|
+
* @param inputs Input feature values.
|
|
44
|
+
* @returns Network predictions.
|
|
45
|
+
*/
|
|
46
|
+
parameters() {
|
|
47
|
+
return this.layers.flatMap((layer) => layer.parameters());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runs a forward pass through the network.
|
|
51
|
+
* @param inputs Input feature values.
|
|
52
|
+
* @returns Network predictions.
|
|
53
|
+
*/
|
|
54
|
+
zeroGrad() {
|
|
55
|
+
for (const parameter of this.parameters()) {
|
|
56
|
+
parameter.zeroGrad();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.MLP = MLP;
|
|
61
|
+
//# sourceMappingURL=MLP.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MLP.js","sourceRoot":"","sources":["../../src/nn/MLP.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAE3C,mCAAgC;AAEhC;;GAEG;AACH,MAAa,GAAG;IAGd;;;;;OAKG;IACH,YACE,SAAiB,EACjB,UAAoB,EACpB,OAGC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;QACtD,CAAC;QAED,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,MAAM,CAAC;QAC7D,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,MAAM,CAAC;QAE7D,MAAM,KAAK,GAAG,CAAC,SAAS,EAAE,GAAG,UAAU,CAAC,CAAC;QAEzC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC;QAEjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,aAAa,GAAG,CAAC,KAAK,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;YAElD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,IAAI,aAAK,CACP,KAAK,CAAC,CAAC,CAAE,EACT,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,EACb,aAAa,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CACpD,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,MAAgB;QAC7B,IAAI,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,WAAG,EAAC,KAAK,CAAC,CAAC,CAAC;QAE/C,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;OAIG;IACI,UAAU;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED;;;;OAIG;IACI,QAAQ;QACb,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;YAC1C,SAAS,CAAC,QAAQ,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;CACF;AA3ED,kBA2EC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Value } from '../core/Value';
|
|
2
|
+
export type Activation = 'tanh' | 'relu' | 'none';
|
|
3
|
+
/**
|
|
4
|
+
* Fully connected neuron with trainable weights and bias.
|
|
5
|
+
*/
|
|
6
|
+
export declare class Neuron {
|
|
7
|
+
/** Trainable weights applied to each input feature. */
|
|
8
|
+
private weights;
|
|
9
|
+
/** Trainable bias added to the weighted sum. */
|
|
10
|
+
private bias;
|
|
11
|
+
/** Activation function applied to the neuron output. */
|
|
12
|
+
private activation;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a neuron with randomly initialized weights.
|
|
15
|
+
* @param inputSize Number of expected input features.
|
|
16
|
+
* @param activation Activation function applied to the output.
|
|
17
|
+
*/
|
|
18
|
+
constructor(inputSize: number, activation?: Activation);
|
|
19
|
+
/**
|
|
20
|
+
* Computes the neuron output for a given set of inputs.
|
|
21
|
+
* @param inputs Input values.
|
|
22
|
+
* @returns Activated neuron output.
|
|
23
|
+
*/
|
|
24
|
+
forward(inputs: Value[]): Value;
|
|
25
|
+
/**
|
|
26
|
+
* Returns all trainable parameters of the neuron.
|
|
27
|
+
* @returns Weights and bias.
|
|
28
|
+
*/
|
|
29
|
+
parameters(): Value[];
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=Neuron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Neuron.d.ts","sourceRoot":"","sources":["../../src/nn/Neuron.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAO,MAAM,eAAe,CAAC;AAE3C,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAElD;;GAEG;AACH,qBAAa,MAAM;IACjB,uDAAuD;IACvD,OAAO,CAAC,OAAO,CAAU;IAEzB,gDAAgD;IAChD,OAAO,CAAC,IAAI,CAAQ;IAEpB,wDAAwD;IACxD,OAAO,CAAC,UAAU,CAAa;IAE/B;;;;OAIG;gBACS,SAAS,EAAE,MAAM,EAAE,UAAU,GAAE,UAAmB;IAM9D;;;;OAIG;IACI,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK;IAmBtC;;;OAGG;IACI,UAAU,IAAI,KAAK,EAAE;CAG7B"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Neuron = void 0;
|
|
4
|
+
const Value_1 = require("../core/Value");
|
|
5
|
+
/**
|
|
6
|
+
* Fully connected neuron with trainable weights and bias.
|
|
7
|
+
*/
|
|
8
|
+
class Neuron {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a neuron with randomly initialized weights.
|
|
11
|
+
* @param inputSize Number of expected input features.
|
|
12
|
+
* @param activation Activation function applied to the output.
|
|
13
|
+
*/
|
|
14
|
+
constructor(inputSize, activation = 'tanh') {
|
|
15
|
+
this.weights = Array.from({ length: inputSize }, () => (0, Value_1.val)(randomWeight()));
|
|
16
|
+
this.bias = (0, Value_1.val)(0);
|
|
17
|
+
this.activation = activation;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Computes the neuron output for a given set of inputs.
|
|
21
|
+
* @param inputs Input values.
|
|
22
|
+
* @returns Activated neuron output.
|
|
23
|
+
*/
|
|
24
|
+
forward(inputs) {
|
|
25
|
+
if (inputs.length !== this.weights.length) {
|
|
26
|
+
throw new Error(`Expected ${this.weights.length} inputs, received ${inputs.length}`);
|
|
27
|
+
}
|
|
28
|
+
let output = this.bias;
|
|
29
|
+
for (let i = 0; i < this.weights.length; i++) {
|
|
30
|
+
output = output.add(this.weights[i].mul(inputs[i]));
|
|
31
|
+
}
|
|
32
|
+
if (this.activation === 'tanh')
|
|
33
|
+
return output.tanh();
|
|
34
|
+
if (this.activation === 'relu')
|
|
35
|
+
return output.relu();
|
|
36
|
+
return output;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns all trainable parameters of the neuron.
|
|
40
|
+
* @returns Weights and bias.
|
|
41
|
+
*/
|
|
42
|
+
parameters() {
|
|
43
|
+
return [...this.weights, this.bias];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.Neuron = Neuron;
|
|
47
|
+
function randomWeight() {
|
|
48
|
+
return Math.random() * 2 - 1;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=Neuron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Neuron.js","sourceRoot":"","sources":["../../src/nn/Neuron.ts"],"names":[],"mappings":";;;AAAA,yCAA2C;AAI3C;;GAEG;AACH,MAAa,MAAM;IAUjB;;;;OAIG;IACH,YAAY,SAAiB,EAAE,aAAyB,MAAM;QAC5D,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,GAAG,EAAE,CAAC,IAAA,WAAG,EAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC5E,IAAI,CAAC,IAAI,GAAG,IAAA,WAAG,EAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED;;;;OAIG;IACI,OAAO,CAAC,MAAe;QAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,YAAY,IAAI,CAAC,OAAO,CAAC,MAAM,qBAAqB,MAAM,CAAC,MAAM,EAAE,CACpE,CAAC;QACJ,CAAC;QAED,IAAI,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7C,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM;YAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;QACrD,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM;YAAE,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;QAErD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,UAAU;QACf,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACtC,CAAC;CACF;AApDD,wBAoDC;AAED,SAAS,YAAY;IACnB,OAAO,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nn/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAC;AAC9B,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/nn/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sgd = exports.mse = exports.MLP = exports.val = exports.Value = void 0;
|
|
4
|
+
var Value_1 = require("../core/Value");
|
|
5
|
+
Object.defineProperty(exports, "Value", { enumerable: true, get: function () { return Value_1.Value; } });
|
|
6
|
+
Object.defineProperty(exports, "val", { enumerable: true, get: function () { return Value_1.val; } });
|
|
7
|
+
var MLP_1 = require("./MLP");
|
|
8
|
+
Object.defineProperty(exports, "MLP", { enumerable: true, get: function () { return MLP_1.MLP; } });
|
|
9
|
+
var loss_1 = require("./loss");
|
|
10
|
+
Object.defineProperty(exports, "mse", { enumerable: true, get: function () { return loss_1.mse; } });
|
|
11
|
+
var optim_1 = require("./optim");
|
|
12
|
+
Object.defineProperty(exports, "sgd", { enumerable: true, get: function () { return optim_1.sgd; } });
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nn/index.ts"],"names":[],"mappings":";;;AAAA,uCAA2C;AAAlC,8FAAA,KAAK,OAAA;AAAE,4FAAA,GAAG,OAAA;AAEnB,6BAA4B;AAAnB,0FAAA,GAAG,OAAA;AACZ,+BAA6B;AAApB,2FAAA,GAAG,OAAA;AACZ,iCAA8B;AAArB,4FAAA,GAAG,OAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Value } from '../core/Value';
|
|
2
|
+
/**
|
|
3
|
+
* Computes mean squared error between predictions and targets.
|
|
4
|
+
* @param predictions Model predictions.
|
|
5
|
+
* @param targets Expected values.
|
|
6
|
+
* @returns Scalar loss value.
|
|
7
|
+
*/
|
|
8
|
+
export declare function mse(predictions: Value[], targets: number[]): Value;
|
|
9
|
+
//# sourceMappingURL=loss.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loss.d.ts","sourceRoot":"","sources":["../../src/nn/loss.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAO,MAAM,eAAe,CAAC;AAE3C;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,KAAK,CAelE"}
|
package/dist/nn/loss.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mse = mse;
|
|
4
|
+
const Value_1 = require("../core/Value");
|
|
5
|
+
/**
|
|
6
|
+
* Computes mean squared error between predictions and targets.
|
|
7
|
+
* @param predictions Model predictions.
|
|
8
|
+
* @param targets Expected values.
|
|
9
|
+
* @returns Scalar loss value.
|
|
10
|
+
*/
|
|
11
|
+
function mse(predictions, targets) {
|
|
12
|
+
if (predictions.length !== targets.length) {
|
|
13
|
+
throw new Error(`Expected ${predictions.length} targets, received ${targets.length}`);
|
|
14
|
+
}
|
|
15
|
+
let loss = (0, Value_1.val)(0);
|
|
16
|
+
for (let i = 0; i < predictions.length; i++) {
|
|
17
|
+
const diff = predictions[i].sub(targets[i]);
|
|
18
|
+
loss = loss.add(diff.pow(2));
|
|
19
|
+
}
|
|
20
|
+
return loss.div(predictions.length);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=loss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loss.js","sourceRoot":"","sources":["../../src/nn/loss.ts"],"names":[],"mappings":";;AAQA,kBAeC;AAvBD,yCAA2C;AAE3C;;;;;GAKG;AACH,SAAgB,GAAG,CAAC,WAAoB,EAAE,OAAiB;IACzD,IAAI,WAAW,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,YAAY,WAAW,CAAC,MAAM,sBAAsB,OAAO,CAAC,MAAM,EAAE,CACrE,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,GAAG,IAAA,WAAG,EAAC,CAAC,CAAC,CAAC;IAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC;QAC9C,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Value } from '../core/Value';
|
|
2
|
+
/**
|
|
3
|
+
* Updates parameters using stochastic gradient descent.
|
|
4
|
+
* @param parameters Trainable parameters.
|
|
5
|
+
* @param learningRate Optimization step size.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sgd(parameters: Value[], learningRate: number): void;
|
|
8
|
+
//# sourceMappingURL=optim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optim.d.ts","sourceRoot":"","sources":["../../src/nn/optim.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAEtC;;;;GAIG;AACH,wBAAgB,GAAG,CAAC,UAAU,EAAE,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAInE"}
|
package/dist/nn/optim.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sgd = sgd;
|
|
4
|
+
/**
|
|
5
|
+
* Updates parameters using stochastic gradient descent.
|
|
6
|
+
* @param parameters Trainable parameters.
|
|
7
|
+
* @param learningRate Optimization step size.
|
|
8
|
+
*/
|
|
9
|
+
function sgd(parameters, learningRate) {
|
|
10
|
+
for (const parameter of parameters) {
|
|
11
|
+
parameter.data -= learningRate * parameter.grad;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=optim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optim.js","sourceRoot":"","sources":["../../src/nn/optim.ts"],"names":[],"mappings":";;AAOA,kBAIC;AATD;;;;GAIG;AACH,SAAgB,GAAG,CAAC,UAAmB,EAAE,YAAoB;IAC3D,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,SAAS,CAAC,IAAI,IAAI,YAAY,GAAG,SAAS,CAAC,IAAI,CAAC;IAClD,CAAC;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "autograd-ts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A tiny reverse-mode automatic differentiation engine in TypeScript",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts"
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "vitest run tests/value.test.ts",
|
|
17
|
+
"test": "vitest run",
|
|
18
|
+
"test:watch": "vitest",
|
|
19
|
+
"prepublishOnly": "npm run build && npm run test"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"autograd",
|
|
23
|
+
"machine-learning",
|
|
24
|
+
"neural-networks",
|
|
25
|
+
"automatic-differentiation",
|
|
26
|
+
"typescript"
|
|
27
|
+
],
|
|
28
|
+
"author": "Eyas Ranjous <eyas.ranjous@gmail.com>",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/node": "^20.0.0",
|
|
32
|
+
"typescript": "^5.3.0",
|
|
33
|
+
"vitest": "^2.0.0"
|
|
34
|
+
}
|
|
35
|
+
}
|