simplegrad 0.0.2__tar.gz
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.
- simplegrad-0.0.2/MANIFEST.in +5 -0
- simplegrad-0.0.2/MANIFEST.md +78 -0
- simplegrad-0.0.2/PKG-INFO +92 -0
- simplegrad-0.0.2/README.md +105 -0
- simplegrad-0.0.2/py-simplegrad/simplegrad-dev/__init__.py +3 -0
- simplegrad-0.0.2/py-simplegrad/simplegrad-dev/py.typed +0 -0
- simplegrad-0.0.2/py-simplegrad/simplegrad-dev/simplegrad.cpython-312-x86_64-linux-gnu.so +0 -0
- simplegrad-0.0.2/py-simplegrad/simplegrad-dev/simplegrad.pyi +262 -0
- simplegrad-0.0.2/setup.cfg +4 -0
- simplegrad-0.0.2/setup.py +26 -0
- simplegrad-0.0.2/simplegrad.egg-info/PKG-INFO +92 -0
- simplegrad-0.0.2/simplegrad.egg-info/SOURCES.txt +12 -0
- simplegrad-0.0.2/simplegrad.egg-info/dependency_links.txt +1 -0
- simplegrad-0.0.2/simplegrad.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# SimpleGrad
|
|
2
|
+
|
|
3
|
+
SimpleGrad is a lightweight automatic differentiation library written in C++ with Python bindings.
|
|
4
|
+
|
|
5
|
+
### Compatible Operating Systems:
|
|
6
|
+
- Linux (x86_64 architecture only)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
```bash
|
|
10
|
+
pip install simplegrad
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- Multi-layer perceptron (MLP) which can be used for regression and classification tasks
|
|
16
|
+
- Supports basic arithmetic operations
|
|
17
|
+
- Lightweight and easy to use
|
|
18
|
+
- Gradient computation
|
|
19
|
+
- Backpropagation
|
|
20
|
+
- Numpy compatibility
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
Here's a quick example of how to use MLP in SimpleGrad:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from simplegrad import MLP, Node
|
|
29
|
+
from sklearn import datasets
|
|
30
|
+
|
|
31
|
+
# Define the model
|
|
32
|
+
X, y = datasets.make_classification(
|
|
33
|
+
n_samples=1000,
|
|
34
|
+
n_features=10,
|
|
35
|
+
n_classes=2,
|
|
36
|
+
random_state=42, # for reproducibility
|
|
37
|
+
)
|
|
38
|
+
lr = 0.01
|
|
39
|
+
batch_size = 16
|
|
40
|
+
epochs = 10
|
|
41
|
+
|
|
42
|
+
# Define the model
|
|
43
|
+
model = MLP(
|
|
44
|
+
10, [16, 1]
|
|
45
|
+
) # 2 input nodes, 2 hidden layers with arbitrary sizes, 1 output node
|
|
46
|
+
|
|
47
|
+
# Training data
|
|
48
|
+
n_batches = (len(X) + batch_size - 1) // batch_size # Ceiling division
|
|
49
|
+
|
|
50
|
+
for epoch in range(epochs):
|
|
51
|
+
epoch_loss = 0.0
|
|
52
|
+
for i in range(0, len(X), batch_size):
|
|
53
|
+
batch_X = X[i : i + batch_size]
|
|
54
|
+
batch_y = y[i : i + batch_size]
|
|
55
|
+
current_batch_size = len(batch_X) # Handle last batch
|
|
56
|
+
|
|
57
|
+
batch_loss = 0.0
|
|
58
|
+
#model.zero_grad() # gradients are automatically reset after step function
|
|
59
|
+
|
|
60
|
+
# Accumulate gradients over batch
|
|
61
|
+
for x, y_true in zip(batch_X, batch_y):
|
|
62
|
+
y_hat = model(x)[0]
|
|
63
|
+
y_true = Node(y_true)
|
|
64
|
+
loss = (y_hat - y_true) ** 2
|
|
65
|
+
loss = loss * (1.0 / current_batch_size) # Normalize loss
|
|
66
|
+
batch_loss += loss.data()
|
|
67
|
+
loss.backward()
|
|
68
|
+
|
|
69
|
+
model.step(lr) # Update weights using accumulated gradients
|
|
70
|
+
del loss, y_hat, y_true # Clean up
|
|
71
|
+
epoch_loss += batch_loss
|
|
72
|
+
|
|
73
|
+
# Average loss over all batches
|
|
74
|
+
print(f"Epoch {epoch+1}, Average Loss: {epoch_loss/n_batches:.3f}")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: simplegrad
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Automatic differentiation library for basic arithmetic operations
|
|
5
|
+
Home-page: https://github.com/deniztemur00/simplegrad.git
|
|
6
|
+
Author: Deniz
|
|
7
|
+
Author-email: deniztemur00@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# SimpleGrad
|
|
16
|
+
|
|
17
|
+
SimpleGrad is a lightweight automatic differentiation library written in C++ with Python bindings.
|
|
18
|
+
|
|
19
|
+
### Compatible Operating Systems:
|
|
20
|
+
- Linux (x86_64 architecture only)
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
```bash
|
|
24
|
+
pip install simplegrad
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Multi-layer perceptron (MLP) which can be used for regression and classification tasks
|
|
30
|
+
- Supports basic arithmetic operations
|
|
31
|
+
- Lightweight and easy to use
|
|
32
|
+
- Gradient computation
|
|
33
|
+
- Backpropagation
|
|
34
|
+
- Numpy compatibility
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Here's a quick example of how to use MLP in SimpleGrad:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from simplegrad import MLP, Node
|
|
43
|
+
from sklearn import datasets
|
|
44
|
+
|
|
45
|
+
# Define the model
|
|
46
|
+
X, y = datasets.make_classification(
|
|
47
|
+
n_samples=1000,
|
|
48
|
+
n_features=10,
|
|
49
|
+
n_classes=2,
|
|
50
|
+
random_state=42, # for reproducibility
|
|
51
|
+
)
|
|
52
|
+
lr = 0.01
|
|
53
|
+
batch_size = 16
|
|
54
|
+
epochs = 10
|
|
55
|
+
|
|
56
|
+
# Define the model
|
|
57
|
+
model = MLP(
|
|
58
|
+
10, [16, 1]
|
|
59
|
+
) # 2 input nodes, 2 hidden layers with arbitrary sizes, 1 output node
|
|
60
|
+
|
|
61
|
+
# Training data
|
|
62
|
+
n_batches = (len(X) + batch_size - 1) // batch_size # Ceiling division
|
|
63
|
+
|
|
64
|
+
for epoch in range(epochs):
|
|
65
|
+
epoch_loss = 0.0
|
|
66
|
+
for i in range(0, len(X), batch_size):
|
|
67
|
+
batch_X = X[i : i + batch_size]
|
|
68
|
+
batch_y = y[i : i + batch_size]
|
|
69
|
+
current_batch_size = len(batch_X) # Handle last batch
|
|
70
|
+
|
|
71
|
+
batch_loss = 0.0
|
|
72
|
+
#model.zero_grad() # gradients are automatically reset after step function
|
|
73
|
+
|
|
74
|
+
# Accumulate gradients over batch
|
|
75
|
+
for x, y_true in zip(batch_X, batch_y):
|
|
76
|
+
y_hat = model(x)[0]
|
|
77
|
+
y_true = Node(y_true)
|
|
78
|
+
loss = (y_hat - y_true) ** 2
|
|
79
|
+
loss = loss * (1.0 / current_batch_size) # Normalize loss
|
|
80
|
+
batch_loss += loss.data()
|
|
81
|
+
loss.backward()
|
|
82
|
+
|
|
83
|
+
model.step(lr) # Update weights using accumulated gradients
|
|
84
|
+
del loss, y_hat, y_true # Clean up
|
|
85
|
+
epoch_loss += batch_loss
|
|
86
|
+
|
|
87
|
+
# Average loss over all batches
|
|
88
|
+
print(f"Epoch {epoch+1}, Average Loss: {epoch_loss/n_batches:.3f}")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# SimpleGrad
|
|
2
|
+
|
|
3
|
+
SimpleGrad is a lightweight automatic differentiation library written in C++ with Python bindings.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Python 3.10 or higher
|
|
8
|
+
- g++/gcc with C++17 support
|
|
9
|
+
- CMake 3.12 or higher
|
|
10
|
+
- pybind11
|
|
11
|
+
|
|
12
|
+
## Build & Installation
|
|
13
|
+
|
|
14
|
+
1. Clone the repository:
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/deniztemur00/simplegrad.git
|
|
17
|
+
cd simplegrad
|
|
18
|
+
```
|
|
19
|
+
2. Build with makefile:
|
|
20
|
+
```bash
|
|
21
|
+
make build-release
|
|
22
|
+
```
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Multi-layer perceptron (MLP) which can be used for regression and classification tasks
|
|
26
|
+
- Supports basic arithmetic operations
|
|
27
|
+
- Lightweight and easy to use
|
|
28
|
+
- Gradient computation
|
|
29
|
+
- Backpropagation
|
|
30
|
+
- Numpy compatibility
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Here's a quick example of how to use MLP in SimpleGrad:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from simplegrad import MLP, Node
|
|
39
|
+
from sklearn import datasets
|
|
40
|
+
|
|
41
|
+
# Define the model
|
|
42
|
+
X, y = datasets.make_classification(
|
|
43
|
+
n_samples=1000,
|
|
44
|
+
n_features=10,
|
|
45
|
+
n_classes=2,
|
|
46
|
+
random_state=42, # for reproducibility
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
lr = 0.01
|
|
51
|
+
batch_size = 16
|
|
52
|
+
epochs = 10
|
|
53
|
+
|
|
54
|
+
# Define the model
|
|
55
|
+
model = MLP(
|
|
56
|
+
10, [12, 1]
|
|
57
|
+
) # 2 input nodes, 2 hidden layers with arbitrary sizes, 1 output node
|
|
58
|
+
|
|
59
|
+
# Training data
|
|
60
|
+
n_batches = (len(X) + batch_size - 1) // batch_size # Ceiling division
|
|
61
|
+
|
|
62
|
+
for epoch in range(epochs):
|
|
63
|
+
epoch_loss = 0.0
|
|
64
|
+
for i in range(0, len(X), batch_size):
|
|
65
|
+
batch_X = X[i : i + batch_size]
|
|
66
|
+
batch_y = y[i : i + batch_size]
|
|
67
|
+
current_batch_size = len(batch_X) # Handle last batch
|
|
68
|
+
|
|
69
|
+
batch_loss = 0.0
|
|
70
|
+
#model.zero_grad() # gradients are automatically reset after step function
|
|
71
|
+
|
|
72
|
+
# Accumulate gradients over batch
|
|
73
|
+
for x, y_true in zip(batch_X, batch_y):
|
|
74
|
+
y_hat = model(x)[0]
|
|
75
|
+
y_true = Node(y_true)
|
|
76
|
+
loss = (y_hat - y_true) ** 2
|
|
77
|
+
loss = loss * (1.0 / current_batch_size) # Normalize loss
|
|
78
|
+
batch_loss += loss.data()
|
|
79
|
+
loss.backward()
|
|
80
|
+
|
|
81
|
+
model.step(lr) # Update weights using accumulated gradients
|
|
82
|
+
epoch_loss += batch_loss
|
|
83
|
+
|
|
84
|
+
# Average loss over all batches
|
|
85
|
+
print(f"Epoch {epoch+1}, Average Loss: {epoch_loss/n_batches:.3f}")
|
|
86
|
+
```
|
|
87
|
+
You can execute the above code by running the following command:
|
|
88
|
+
```bash
|
|
89
|
+
make run
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Testing
|
|
93
|
+
Tests are written to ensure the correctness of the Node class. Thus making sure MLP works as expected. You can run tests with following command:
|
|
94
|
+
```bash
|
|
95
|
+
make test
|
|
96
|
+
```
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
This project is licensed under the MIT License.
|
|
100
|
+
|
|
101
|
+
## Acknowledgements
|
|
102
|
+
|
|
103
|
+
This project was inspired by the [micrograd](https://github.com/karpathy/micrograd) project by Andrej Karpathy.
|
|
104
|
+
|
|
105
|
+
|
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
from typing import List, Union
|
|
2
|
+
|
|
3
|
+
class Node:
|
|
4
|
+
def __init__(self, value: float) -> None:
|
|
5
|
+
"""
|
|
6
|
+
Initializes a new node with the given value.
|
|
7
|
+
|
|
8
|
+
Parameters:
|
|
9
|
+
value (float): The numeric value to store in the node.
|
|
10
|
+
"""
|
|
11
|
+
...
|
|
12
|
+
|
|
13
|
+
def data(self) -> float:
|
|
14
|
+
"""
|
|
15
|
+
Retrieves the data stored in the node.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
float: The data value of the node.
|
|
19
|
+
"""
|
|
20
|
+
...
|
|
21
|
+
|
|
22
|
+
def grad(self) -> float:
|
|
23
|
+
"""
|
|
24
|
+
Retrieves the gradient associated with the node.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
float: The gradient value of the node.
|
|
28
|
+
"""
|
|
29
|
+
...
|
|
30
|
+
|
|
31
|
+
def backward(self) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Performs backpropagation to compute gradients of all nodes in the computational graph.
|
|
34
|
+
"""
|
|
35
|
+
...
|
|
36
|
+
|
|
37
|
+
def relu(self) -> "Node":
|
|
38
|
+
"""
|
|
39
|
+
Applies the ReLU activation function to the node.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Node: A new node after applying the ReLU function.
|
|
43
|
+
"""
|
|
44
|
+
...
|
|
45
|
+
|
|
46
|
+
def __add__(self, other: Union["Node", float]) -> "Node":
|
|
47
|
+
"""
|
|
48
|
+
Adds this node with another node or scalar.
|
|
49
|
+
|
|
50
|
+
Parameters:
|
|
51
|
+
other (Union[Node, float]): The node or scalar to add.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
Node: The result of the addition.
|
|
55
|
+
"""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def __radd__(self, other: Union["Node", float]) -> "Node":
|
|
59
|
+
"""
|
|
60
|
+
Adds another node or scalar to this node (reversed operands).
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
other (Union[Node, float]): The node or scalar to add.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Node: The result of the addition.
|
|
67
|
+
"""
|
|
68
|
+
...
|
|
69
|
+
|
|
70
|
+
def __mul__(self, other: Union["Node", float]) -> "Node":
|
|
71
|
+
"""
|
|
72
|
+
Multiplies this node with another node or scalar.
|
|
73
|
+
|
|
74
|
+
Parameters:
|
|
75
|
+
other (Union[Node, float]): The node or scalar to multiply.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Node: The result of the multiplication.
|
|
79
|
+
"""
|
|
80
|
+
...
|
|
81
|
+
|
|
82
|
+
def __rmul__(self, other: Union["Node", float]) -> "Node":
|
|
83
|
+
"""
|
|
84
|
+
Multiplies another node or scalar with this node (reversed operands).
|
|
85
|
+
|
|
86
|
+
Parameters:
|
|
87
|
+
other (Union[Node, float]): The node or scalar to multiply.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Node: The result of the multiplication.
|
|
91
|
+
"""
|
|
92
|
+
...
|
|
93
|
+
|
|
94
|
+
def __sub__(self, other: Union["Node", float]) -> "Node":
|
|
95
|
+
"""
|
|
96
|
+
Subtracts another node or scalar from this node.
|
|
97
|
+
|
|
98
|
+
Parameters:
|
|
99
|
+
other (Union[Node, float]): The node or scalar to subtract.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Node: The result of the subtraction.
|
|
103
|
+
"""
|
|
104
|
+
...
|
|
105
|
+
|
|
106
|
+
def __rsub__(self, other: Union["Node", float]) -> "Node":
|
|
107
|
+
"""
|
|
108
|
+
Subtracts this node from another node or scalar (reversed operands).
|
|
109
|
+
|
|
110
|
+
Parameters:
|
|
111
|
+
other (Union[Node, float]): The node or scalar to subtract from.
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Node: The result of the subtraction.
|
|
115
|
+
"""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def __truediv__(self, other: Union["Node", float]) -> "Node":
|
|
119
|
+
"""
|
|
120
|
+
Divides this node by another node or scalar.
|
|
121
|
+
|
|
122
|
+
Parameters:
|
|
123
|
+
other (Union[Node, float]): The node or scalar to divide by.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Node: The result of the division.
|
|
127
|
+
"""
|
|
128
|
+
...
|
|
129
|
+
|
|
130
|
+
def __rtruediv__(self, other: Union["Node", float]) -> "Node":
|
|
131
|
+
"""
|
|
132
|
+
Divides another node or scalar by this node (reversed operands).
|
|
133
|
+
|
|
134
|
+
Parameters:
|
|
135
|
+
other (Union[Node, float]): The node or scalar to divide.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
Node: The result of the division.
|
|
139
|
+
"""
|
|
140
|
+
...
|
|
141
|
+
|
|
142
|
+
class Module:
|
|
143
|
+
def zero_grad(self) -> None:
|
|
144
|
+
"""
|
|
145
|
+
Resets the gradients of all parameters to zero.
|
|
146
|
+
"""
|
|
147
|
+
...
|
|
148
|
+
|
|
149
|
+
def parameters(self) -> List[Node]:
|
|
150
|
+
"""
|
|
151
|
+
Retrieves all parameter nodes within the module.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
List[Node]: A list of parameter nodes.
|
|
155
|
+
"""
|
|
156
|
+
...
|
|
157
|
+
|
|
158
|
+
class Neuron(Module):
|
|
159
|
+
def __init__(self, nin: int, nonlin: bool = True) -> None:
|
|
160
|
+
"""
|
|
161
|
+
Initializes a neuron with a specified number of inputs.
|
|
162
|
+
|
|
163
|
+
Parameters:
|
|
164
|
+
nin (int): Number of input features.
|
|
165
|
+
nonlin (bool): If True, applies a non-linear activation function (ReLU).
|
|
166
|
+
"""
|
|
167
|
+
...
|
|
168
|
+
|
|
169
|
+
def __call__(self, x: List[Node]) -> Node:
|
|
170
|
+
"""
|
|
171
|
+
Performs the forward pass of the neuron.
|
|
172
|
+
|
|
173
|
+
Parameters:
|
|
174
|
+
x (List[Node]): A list of input nodes.
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
Node: The output node after applying weights, bias, and activation.
|
|
178
|
+
"""
|
|
179
|
+
...
|
|
180
|
+
|
|
181
|
+
def parameters(self) -> List[Node]:
|
|
182
|
+
"""
|
|
183
|
+
Retrieves the parameters (weights and bias) of the neuron.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
List[Node]: A list containing the weight nodes and bias node.
|
|
187
|
+
"""
|
|
188
|
+
...
|
|
189
|
+
|
|
190
|
+
class Layer(Module):
|
|
191
|
+
def __init__(self, nin: int, nout: int) -> None:
|
|
192
|
+
"""
|
|
193
|
+
Initializes a layer composed of multiple neurons.
|
|
194
|
+
|
|
195
|
+
Parameters:
|
|
196
|
+
nin (int): Number of input features.
|
|
197
|
+
nout (int): Number of neurons in the layer.
|
|
198
|
+
"""
|
|
199
|
+
...
|
|
200
|
+
|
|
201
|
+
def __call__(self, x: List[Node]) -> List[Node]:
|
|
202
|
+
"""
|
|
203
|
+
Performs the forward pass of the layer.
|
|
204
|
+
|
|
205
|
+
Parameters:
|
|
206
|
+
x (List[Node]): A list of input nodes.
|
|
207
|
+
|
|
208
|
+
Returns:
|
|
209
|
+
List[Node]: A list of output nodes from each neuron in the layer.
|
|
210
|
+
"""
|
|
211
|
+
...
|
|
212
|
+
|
|
213
|
+
def parameters(self) -> List[Node]:
|
|
214
|
+
"""
|
|
215
|
+
Retrieves the parameters from all neurons in the layer.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
List[Node]: A list of parameter nodes from all neurons.
|
|
219
|
+
"""
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
class MLP(Module):
|
|
223
|
+
def __init__(self, nin: int, nouts: List[int]) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Initializes a Multi-Layer Perceptron (MLP) model.
|
|
226
|
+
|
|
227
|
+
Parameters:
|
|
228
|
+
nin (int): Number of input features.
|
|
229
|
+
nouts (List[int]): A list specifying the number of neurons in each layer.
|
|
230
|
+
"""
|
|
231
|
+
...
|
|
232
|
+
|
|
233
|
+
def __call__(self, x: Union[List[Node], List[float]]) -> List[Node]:
|
|
234
|
+
"""
|
|
235
|
+
Performs the forward pass of the MLP.
|
|
236
|
+
|
|
237
|
+
Parameters:
|
|
238
|
+
x (Union[List[Node], List[float]]): Input data as a list of nodes or raw values.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
List[Node]: Output nodes after passing through the network.
|
|
242
|
+
"""
|
|
243
|
+
...
|
|
244
|
+
|
|
245
|
+
def parameters(self) -> List[Node]:
|
|
246
|
+
"""
|
|
247
|
+
Retrieves the parameters from all layers of the MLP.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
List[Node]: A list of parameter nodes from all layers.
|
|
251
|
+
"""
|
|
252
|
+
...
|
|
253
|
+
|
|
254
|
+
def step(self, lr: float) -> None:
|
|
255
|
+
"""
|
|
256
|
+
Updates the parameters using gradient descent.
|
|
257
|
+
|
|
258
|
+
Parameters:
|
|
259
|
+
lr (float): The learning rate for parameter updates.
|
|
260
|
+
"""
|
|
261
|
+
...
|
|
262
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
setup(
|
|
5
|
+
name="simplegrad",
|
|
6
|
+
version="0.0.2",
|
|
7
|
+
description="Automatic differentiation library for basic arithmetic operations",
|
|
8
|
+
author="Deniz",
|
|
9
|
+
url="https://github.com/deniztemur00/simplegrad.git",
|
|
10
|
+
long_description=open("MANIFEST.md").read(),
|
|
11
|
+
long_description_content_type="text/markdown",
|
|
12
|
+
package_dir={"simplegrad": "py-simplegrad/simplegrad-dev"},
|
|
13
|
+
packages=["simplegrad"],
|
|
14
|
+
package_data={
|
|
15
|
+
"simplegrad": ["*.pyi", "py.typed", "*.so", "__init__.py"],
|
|
16
|
+
},
|
|
17
|
+
classifiers=[
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"License :: OSI Approved :: MIT License", # Fixed classifier syntax
|
|
20
|
+
"Operating System :: POSIX :: Linux",
|
|
21
|
+
],
|
|
22
|
+
license="MIT",
|
|
23
|
+
author_email="deniztemur00@gmail.com",
|
|
24
|
+
python_requires=">=3.6",
|
|
25
|
+
options={"bdist_wheel": {"universal": True}},
|
|
26
|
+
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: simplegrad
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Automatic differentiation library for basic arithmetic operations
|
|
5
|
+
Home-page: https://github.com/deniztemur00/simplegrad.git
|
|
6
|
+
Author: Deniz
|
|
7
|
+
Author-email: deniztemur00@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
|
|
15
|
+
# SimpleGrad
|
|
16
|
+
|
|
17
|
+
SimpleGrad is a lightweight automatic differentiation library written in C++ with Python bindings.
|
|
18
|
+
|
|
19
|
+
### Compatible Operating Systems:
|
|
20
|
+
- Linux (x86_64 architecture only)
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
```bash
|
|
24
|
+
pip install simplegrad
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- Multi-layer perceptron (MLP) which can be used for regression and classification tasks
|
|
30
|
+
- Supports basic arithmetic operations
|
|
31
|
+
- Lightweight and easy to use
|
|
32
|
+
- Gradient computation
|
|
33
|
+
- Backpropagation
|
|
34
|
+
- Numpy compatibility
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
Here's a quick example of how to use MLP in SimpleGrad:
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from simplegrad import MLP, Node
|
|
43
|
+
from sklearn import datasets
|
|
44
|
+
|
|
45
|
+
# Define the model
|
|
46
|
+
X, y = datasets.make_classification(
|
|
47
|
+
n_samples=1000,
|
|
48
|
+
n_features=10,
|
|
49
|
+
n_classes=2,
|
|
50
|
+
random_state=42, # for reproducibility
|
|
51
|
+
)
|
|
52
|
+
lr = 0.01
|
|
53
|
+
batch_size = 16
|
|
54
|
+
epochs = 10
|
|
55
|
+
|
|
56
|
+
# Define the model
|
|
57
|
+
model = MLP(
|
|
58
|
+
10, [16, 1]
|
|
59
|
+
) # 2 input nodes, 2 hidden layers with arbitrary sizes, 1 output node
|
|
60
|
+
|
|
61
|
+
# Training data
|
|
62
|
+
n_batches = (len(X) + batch_size - 1) // batch_size # Ceiling division
|
|
63
|
+
|
|
64
|
+
for epoch in range(epochs):
|
|
65
|
+
epoch_loss = 0.0
|
|
66
|
+
for i in range(0, len(X), batch_size):
|
|
67
|
+
batch_X = X[i : i + batch_size]
|
|
68
|
+
batch_y = y[i : i + batch_size]
|
|
69
|
+
current_batch_size = len(batch_X) # Handle last batch
|
|
70
|
+
|
|
71
|
+
batch_loss = 0.0
|
|
72
|
+
#model.zero_grad() # gradients are automatically reset after step function
|
|
73
|
+
|
|
74
|
+
# Accumulate gradients over batch
|
|
75
|
+
for x, y_true in zip(batch_X, batch_y):
|
|
76
|
+
y_hat = model(x)[0]
|
|
77
|
+
y_true = Node(y_true)
|
|
78
|
+
loss = (y_hat - y_true) ** 2
|
|
79
|
+
loss = loss * (1.0 / current_batch_size) # Normalize loss
|
|
80
|
+
batch_loss += loss.data()
|
|
81
|
+
loss.backward()
|
|
82
|
+
|
|
83
|
+
model.step(lr) # Update weights using accumulated gradients
|
|
84
|
+
del loss, y_hat, y_true # Clean up
|
|
85
|
+
epoch_loss += batch_loss
|
|
86
|
+
|
|
87
|
+
# Average loss over all batches
|
|
88
|
+
print(f"Epoch {epoch+1}, Average Loss: {epoch_loss/n_batches:.3f}")
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
MANIFEST.in
|
|
2
|
+
MANIFEST.md
|
|
3
|
+
README.md
|
|
4
|
+
setup.py
|
|
5
|
+
py-simplegrad/simplegrad-dev/__init__.py
|
|
6
|
+
py-simplegrad/simplegrad-dev/py.typed
|
|
7
|
+
py-simplegrad/simplegrad-dev/simplegrad.cpython-312-x86_64-linux-gnu.so
|
|
8
|
+
py-simplegrad/simplegrad-dev/simplegrad.pyi
|
|
9
|
+
simplegrad.egg-info/PKG-INFO
|
|
10
|
+
simplegrad.egg-info/SOURCES.txt
|
|
11
|
+
simplegrad.egg-info/dependency_links.txt
|
|
12
|
+
simplegrad.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
simplegrad
|