NeuralEngine 0.2.4__tar.gz → 0.2.7__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.
- {neuralengine-0.2.4 → neuralengine-0.2.7/NeuralEngine.egg-info}/PKG-INFO +23 -11
- {neuralengine-0.2.4 → neuralengine-0.2.7}/NeuralEngine.egg-info/SOURCES.txt +1 -0
- {neuralengine-0.2.4/NeuralEngine.egg-info → neuralengine-0.2.7}/PKG-INFO +23 -11
- {neuralengine-0.2.4 → neuralengine-0.2.7}/README.md +22 -10
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/config.py +0 -1
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/__init__.py +2 -1
- neuralengine-0.2.7/neuralengine/nn/dataload.py +60 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/loss.py +14 -8
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/metrics.py +47 -23
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/model.py +49 -73
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/optim.py +0 -3
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/tensor.py +2 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/pyproject.toml +1 -1
- {neuralengine-0.2.4 → neuralengine-0.2.7}/setup.py +1 -1
- {neuralengine-0.2.4 → neuralengine-0.2.7}/LICENSE +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/MANIFEST.in +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/NeuralEngine.egg-info/dependency_links.txt +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/NeuralEngine.egg-info/requires.txt +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/NeuralEngine.egg-info/top_level.txt +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/__init__.py +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/nn/layers.py +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/neuralengine/utils.py +0 -0
- {neuralengine-0.2.4 → neuralengine-0.2.7}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: NeuralEngine
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: A framework/library for building and training neural networks.
|
|
5
5
|
Home-page: https://github.com/Prajjwal2404/NeuralEngine
|
|
6
6
|
Author: Prajjwal Pratap Shah
|
|
@@ -123,9 +123,12 @@ ne.set_device(ne.Device.CUDA)
|
|
|
123
123
|
# Load your dataset (example: MNIST)
|
|
124
124
|
x_train, y_train, x_test, y_test = load_mnist_data()
|
|
125
125
|
|
|
126
|
-
y_train = ne.one_hot(y_train)
|
|
126
|
+
y_train = ne.one_hot(y_train) # Preprocess if needed
|
|
127
127
|
y_test = ne.one_hot(y_test)
|
|
128
128
|
|
|
129
|
+
train_data = ne.DataLoader(x_train, y_train, batch_size=10000)
|
|
130
|
+
test_data = ne.DataLoader(x_test, y_test, batch_size=10000, shuffle=False)
|
|
131
|
+
|
|
129
132
|
# Build your model
|
|
130
133
|
model = ne.Model(
|
|
131
134
|
input_size=(28, 28),
|
|
@@ -140,8 +143,8 @@ model(
|
|
|
140
143
|
)
|
|
141
144
|
|
|
142
145
|
# Train and evaluate
|
|
143
|
-
model.train(
|
|
144
|
-
result = model.eval(
|
|
146
|
+
model.train(train_data, epochs=30)
|
|
147
|
+
result = model.eval(test_data)
|
|
145
148
|
```
|
|
146
149
|
|
|
147
150
|
## Project Structure
|
|
@@ -153,6 +156,7 @@ neuralengine/
|
|
|
153
156
|
utils.py
|
|
154
157
|
nn/
|
|
155
158
|
__init__.py
|
|
159
|
+
dataload.py
|
|
156
160
|
layers.py
|
|
157
161
|
loss.py
|
|
158
162
|
metrics.py
|
|
@@ -220,7 +224,7 @@ NeuralEngine offers the following core capabilities:
|
|
|
220
224
|
- `ne.Huber(delta=1.0)`: Huber loss, robust to outliers.
|
|
221
225
|
- `ne.GaussianNLL(eps=1e-7)`: Gaussian Negative Log Likelihood loss for probabilistic regression.
|
|
222
226
|
- `ne.KLDivergence(eps=1e-7)`: Kullback-Leibler Divergence loss for measuring distribution differences.
|
|
223
|
-
- All loss functions inherit from a common base and
|
|
227
|
+
- All loss functions inherit from a common base, support autograd and loss accumulation.
|
|
224
228
|
|
|
225
229
|
### Optimizers
|
|
226
230
|
- `ne.Adam(lr=1e-3, betas=(0.9, 0.99), eps=1e-7, reg=0)`: Adam optimizer (switches to RMSProp if only one beta is provided).
|
|
@@ -228,21 +232,28 @@ NeuralEngine offers the following core capabilities:
|
|
|
228
232
|
- All optimizers support L2 regularization and gradient reset.
|
|
229
233
|
|
|
230
234
|
### Metrics
|
|
231
|
-
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False
|
|
235
|
+
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False)`: Computes accuracy, precision, recall and F1 score for classification tasks.
|
|
232
236
|
- `ne.RMSE()`: Root Mean Squared Error for regression.
|
|
233
237
|
- `ne.R2()`: R2 Score for regression.
|
|
234
|
-
-
|
|
238
|
+
- `ne.Perplexity()`: Perplexity metric for generative models.
|
|
239
|
+
- All metrics store results as dictionaries, support batch evaluation and metric accumulation.
|
|
235
240
|
|
|
236
241
|
### Model API
|
|
237
242
|
- `ne.Model(input_size, optimizer, loss, metrics)`: Create a model specifying input size, optimizer, loss function, and metrics.
|
|
238
243
|
- Add layers by calling the model instance: `model(layer1, layer2, ...)` or using `model.build(layer1, layer2, ...)`.
|
|
239
|
-
- `model.train(
|
|
240
|
-
- `model.eval(
|
|
244
|
+
- `model.train(dataloader, epochs=10, ckpt_interval=None)`: Train the model on dataset, with support for metric/loss reporting and checkpointing per epoch.
|
|
245
|
+
- `model.eval(dataloader)`: Evaluate the model on dataset, disables gradient tracking using `with ne.NoGrad():`, prints loss and metrics, and returns output tensor.
|
|
241
246
|
- Layers are set to training or evaluation mode automatically during `train` and `eval`.
|
|
242
247
|
- `model.save(filename, weights_only=False)`: Save the model architecture or model parameters to a file.
|
|
243
248
|
- `model.load_params(filepath)`: Load model parameters from a saved file.
|
|
244
249
|
- `ne.Model.load_model(filepath)`: Load a model from a saved file.
|
|
245
250
|
|
|
251
|
+
### DataLoader
|
|
252
|
+
- `ne.DataLoader(x, y, dtype=None, batch_size=32, shuffle=True, seed=None, bar=30)`: Create a data loader for batching and shuffling datasets during training and evaluation.
|
|
253
|
+
- Supports lists, tuples, numpy arrays, pandas dataframes and tensors as input data.
|
|
254
|
+
- Provides batching, shuffling, and progress bar display during iteration.
|
|
255
|
+
- Extensible for custom data loading strategies.
|
|
256
|
+
|
|
246
257
|
### Utilities
|
|
247
258
|
- Tensor creation: `tensor(data, requires_grad=False)`, `zeros(shape)`, `ones(shape)`, `rand(shape)`, `randn(shape, xavier=False)`, `randint(low, high, shape)` and their `_like` variants for matching shapes.
|
|
248
259
|
- Tensor operations: `sum`, `max`, `min`, `mean`, `var`, `log`, `sqrt`, `exp`, `abs`, `concat`, `stack`, `where`, `clip`, `array(data, dtype=...)` for elementwise, reduction, and conversion operations.
|
|
@@ -253,8 +264,9 @@ NeuralEngine is designed for easy extension and customization:
|
|
|
253
264
|
- **Custom Layers**: Create new layers by inheriting from the `Layer` base class and implementing the `forward(self, x)` method. You can add parameters, initialization logic, and custom computations as needed. All built-in layers follow this pattern, making it simple to add your own.
|
|
254
265
|
- **Custom Losses**: Define new loss functions by inheriting from the `Loss` base class and implementing the `compute(self, z, y)` method. This allows you to integrate any custom loss logic with autograd support.
|
|
255
266
|
- **Custom Optimizers**: Implement new optimization algorithms by inheriting from the `Optimizer` base class and providing your own `step(self)` method. You can manage optimizer state and parameter updates as required.
|
|
256
|
-
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method.
|
|
257
|
-
-
|
|
267
|
+
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method. This allows you to track any performance measure with metric accumulation.
|
|
268
|
+
- **Custom DataLoaders**: Extend the `DataLoader` class to create specialized data loading strategies. Override the `__getitem__` method to define how batches are constructed.
|
|
269
|
+
- All core components are modular and can be replaced or extended for research or production use.
|
|
258
270
|
|
|
259
271
|
## Contribution Guide
|
|
260
272
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: NeuralEngine
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7
|
|
4
4
|
Summary: A framework/library for building and training neural networks.
|
|
5
5
|
Home-page: https://github.com/Prajjwal2404/NeuralEngine
|
|
6
6
|
Author: Prajjwal Pratap Shah
|
|
@@ -123,9 +123,12 @@ ne.set_device(ne.Device.CUDA)
|
|
|
123
123
|
# Load your dataset (example: MNIST)
|
|
124
124
|
x_train, y_train, x_test, y_test = load_mnist_data()
|
|
125
125
|
|
|
126
|
-
y_train = ne.one_hot(y_train)
|
|
126
|
+
y_train = ne.one_hot(y_train) # Preprocess if needed
|
|
127
127
|
y_test = ne.one_hot(y_test)
|
|
128
128
|
|
|
129
|
+
train_data = ne.DataLoader(x_train, y_train, batch_size=10000)
|
|
130
|
+
test_data = ne.DataLoader(x_test, y_test, batch_size=10000, shuffle=False)
|
|
131
|
+
|
|
129
132
|
# Build your model
|
|
130
133
|
model = ne.Model(
|
|
131
134
|
input_size=(28, 28),
|
|
@@ -140,8 +143,8 @@ model(
|
|
|
140
143
|
)
|
|
141
144
|
|
|
142
145
|
# Train and evaluate
|
|
143
|
-
model.train(
|
|
144
|
-
result = model.eval(
|
|
146
|
+
model.train(train_data, epochs=30)
|
|
147
|
+
result = model.eval(test_data)
|
|
145
148
|
```
|
|
146
149
|
|
|
147
150
|
## Project Structure
|
|
@@ -153,6 +156,7 @@ neuralengine/
|
|
|
153
156
|
utils.py
|
|
154
157
|
nn/
|
|
155
158
|
__init__.py
|
|
159
|
+
dataload.py
|
|
156
160
|
layers.py
|
|
157
161
|
loss.py
|
|
158
162
|
metrics.py
|
|
@@ -220,7 +224,7 @@ NeuralEngine offers the following core capabilities:
|
|
|
220
224
|
- `ne.Huber(delta=1.0)`: Huber loss, robust to outliers.
|
|
221
225
|
- `ne.GaussianNLL(eps=1e-7)`: Gaussian Negative Log Likelihood loss for probabilistic regression.
|
|
222
226
|
- `ne.KLDivergence(eps=1e-7)`: Kullback-Leibler Divergence loss for measuring distribution differences.
|
|
223
|
-
- All loss functions inherit from a common base and
|
|
227
|
+
- All loss functions inherit from a common base, support autograd and loss accumulation.
|
|
224
228
|
|
|
225
229
|
### Optimizers
|
|
226
230
|
- `ne.Adam(lr=1e-3, betas=(0.9, 0.99), eps=1e-7, reg=0)`: Adam optimizer (switches to RMSProp if only one beta is provided).
|
|
@@ -228,21 +232,28 @@ NeuralEngine offers the following core capabilities:
|
|
|
228
232
|
- All optimizers support L2 regularization and gradient reset.
|
|
229
233
|
|
|
230
234
|
### Metrics
|
|
231
|
-
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False
|
|
235
|
+
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False)`: Computes accuracy, precision, recall and F1 score for classification tasks.
|
|
232
236
|
- `ne.RMSE()`: Root Mean Squared Error for regression.
|
|
233
237
|
- `ne.R2()`: R2 Score for regression.
|
|
234
|
-
-
|
|
238
|
+
- `ne.Perplexity()`: Perplexity metric for generative models.
|
|
239
|
+
- All metrics store results as dictionaries, support batch evaluation and metric accumulation.
|
|
235
240
|
|
|
236
241
|
### Model API
|
|
237
242
|
- `ne.Model(input_size, optimizer, loss, metrics)`: Create a model specifying input size, optimizer, loss function, and metrics.
|
|
238
243
|
- Add layers by calling the model instance: `model(layer1, layer2, ...)` or using `model.build(layer1, layer2, ...)`.
|
|
239
|
-
- `model.train(
|
|
240
|
-
- `model.eval(
|
|
244
|
+
- `model.train(dataloader, epochs=10, ckpt_interval=None)`: Train the model on dataset, with support for metric/loss reporting and checkpointing per epoch.
|
|
245
|
+
- `model.eval(dataloader)`: Evaluate the model on dataset, disables gradient tracking using `with ne.NoGrad():`, prints loss and metrics, and returns output tensor.
|
|
241
246
|
- Layers are set to training or evaluation mode automatically during `train` and `eval`.
|
|
242
247
|
- `model.save(filename, weights_only=False)`: Save the model architecture or model parameters to a file.
|
|
243
248
|
- `model.load_params(filepath)`: Load model parameters from a saved file.
|
|
244
249
|
- `ne.Model.load_model(filepath)`: Load a model from a saved file.
|
|
245
250
|
|
|
251
|
+
### DataLoader
|
|
252
|
+
- `ne.DataLoader(x, y, dtype=None, batch_size=32, shuffle=True, seed=None, bar=30)`: Create a data loader for batching and shuffling datasets during training and evaluation.
|
|
253
|
+
- Supports lists, tuples, numpy arrays, pandas dataframes and tensors as input data.
|
|
254
|
+
- Provides batching, shuffling, and progress bar display during iteration.
|
|
255
|
+
- Extensible for custom data loading strategies.
|
|
256
|
+
|
|
246
257
|
### Utilities
|
|
247
258
|
- Tensor creation: `tensor(data, requires_grad=False)`, `zeros(shape)`, `ones(shape)`, `rand(shape)`, `randn(shape, xavier=False)`, `randint(low, high, shape)` and their `_like` variants for matching shapes.
|
|
248
259
|
- Tensor operations: `sum`, `max`, `min`, `mean`, `var`, `log`, `sqrt`, `exp`, `abs`, `concat`, `stack`, `where`, `clip`, `array(data, dtype=...)` for elementwise, reduction, and conversion operations.
|
|
@@ -253,8 +264,9 @@ NeuralEngine is designed for easy extension and customization:
|
|
|
253
264
|
- **Custom Layers**: Create new layers by inheriting from the `Layer` base class and implementing the `forward(self, x)` method. You can add parameters, initialization logic, and custom computations as needed. All built-in layers follow this pattern, making it simple to add your own.
|
|
254
265
|
- **Custom Losses**: Define new loss functions by inheriting from the `Loss` base class and implementing the `compute(self, z, y)` method. This allows you to integrate any custom loss logic with autograd support.
|
|
255
266
|
- **Custom Optimizers**: Implement new optimization algorithms by inheriting from the `Optimizer` base class and providing your own `step(self)` method. You can manage optimizer state and parameter updates as required.
|
|
256
|
-
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method.
|
|
257
|
-
-
|
|
267
|
+
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method. This allows you to track any performance measure with metric accumulation.
|
|
268
|
+
- **Custom DataLoaders**: Extend the `DataLoader` class to create specialized data loading strategies. Override the `__getitem__` method to define how batches are constructed.
|
|
269
|
+
- All core components are modular and can be replaced or extended for research or production use.
|
|
258
270
|
|
|
259
271
|
## Contribution Guide
|
|
260
272
|
|
|
@@ -75,9 +75,12 @@ ne.set_device(ne.Device.CUDA)
|
|
|
75
75
|
# Load your dataset (example: MNIST)
|
|
76
76
|
x_train, y_train, x_test, y_test = load_mnist_data()
|
|
77
77
|
|
|
78
|
-
y_train = ne.one_hot(y_train)
|
|
78
|
+
y_train = ne.one_hot(y_train) # Preprocess if needed
|
|
79
79
|
y_test = ne.one_hot(y_test)
|
|
80
80
|
|
|
81
|
+
train_data = ne.DataLoader(x_train, y_train, batch_size=10000)
|
|
82
|
+
test_data = ne.DataLoader(x_test, y_test, batch_size=10000, shuffle=False)
|
|
83
|
+
|
|
81
84
|
# Build your model
|
|
82
85
|
model = ne.Model(
|
|
83
86
|
input_size=(28, 28),
|
|
@@ -92,8 +95,8 @@ model(
|
|
|
92
95
|
)
|
|
93
96
|
|
|
94
97
|
# Train and evaluate
|
|
95
|
-
model.train(
|
|
96
|
-
result = model.eval(
|
|
98
|
+
model.train(train_data, epochs=30)
|
|
99
|
+
result = model.eval(test_data)
|
|
97
100
|
```
|
|
98
101
|
|
|
99
102
|
## Project Structure
|
|
@@ -105,6 +108,7 @@ neuralengine/
|
|
|
105
108
|
utils.py
|
|
106
109
|
nn/
|
|
107
110
|
__init__.py
|
|
111
|
+
dataload.py
|
|
108
112
|
layers.py
|
|
109
113
|
loss.py
|
|
110
114
|
metrics.py
|
|
@@ -172,7 +176,7 @@ NeuralEngine offers the following core capabilities:
|
|
|
172
176
|
- `ne.Huber(delta=1.0)`: Huber loss, robust to outliers.
|
|
173
177
|
- `ne.GaussianNLL(eps=1e-7)`: Gaussian Negative Log Likelihood loss for probabilistic regression.
|
|
174
178
|
- `ne.KLDivergence(eps=1e-7)`: Kullback-Leibler Divergence loss for measuring distribution differences.
|
|
175
|
-
- All loss functions inherit from a common base and
|
|
179
|
+
- All loss functions inherit from a common base, support autograd and loss accumulation.
|
|
176
180
|
|
|
177
181
|
### Optimizers
|
|
178
182
|
- `ne.Adam(lr=1e-3, betas=(0.9, 0.99), eps=1e-7, reg=0)`: Adam optimizer (switches to RMSProp if only one beta is provided).
|
|
@@ -180,21 +184,28 @@ NeuralEngine offers the following core capabilities:
|
|
|
180
184
|
- All optimizers support L2 regularization and gradient reset.
|
|
181
185
|
|
|
182
186
|
### Metrics
|
|
183
|
-
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False
|
|
187
|
+
- `ne.ClassificationMetrics(num_classes=None, acc=True, prec=False, rec=False, f1=False)`: Computes accuracy, precision, recall and F1 score for classification tasks.
|
|
184
188
|
- `ne.RMSE()`: Root Mean Squared Error for regression.
|
|
185
189
|
- `ne.R2()`: R2 Score for regression.
|
|
186
|
-
-
|
|
190
|
+
- `ne.Perplexity()`: Perplexity metric for generative models.
|
|
191
|
+
- All metrics store results as dictionaries, support batch evaluation and metric accumulation.
|
|
187
192
|
|
|
188
193
|
### Model API
|
|
189
194
|
- `ne.Model(input_size, optimizer, loss, metrics)`: Create a model specifying input size, optimizer, loss function, and metrics.
|
|
190
195
|
- Add layers by calling the model instance: `model(layer1, layer2, ...)` or using `model.build(layer1, layer2, ...)`.
|
|
191
|
-
- `model.train(
|
|
192
|
-
- `model.eval(
|
|
196
|
+
- `model.train(dataloader, epochs=10, ckpt_interval=None)`: Train the model on dataset, with support for metric/loss reporting and checkpointing per epoch.
|
|
197
|
+
- `model.eval(dataloader)`: Evaluate the model on dataset, disables gradient tracking using `with ne.NoGrad():`, prints loss and metrics, and returns output tensor.
|
|
193
198
|
- Layers are set to training or evaluation mode automatically during `train` and `eval`.
|
|
194
199
|
- `model.save(filename, weights_only=False)`: Save the model architecture or model parameters to a file.
|
|
195
200
|
- `model.load_params(filepath)`: Load model parameters from a saved file.
|
|
196
201
|
- `ne.Model.load_model(filepath)`: Load a model from a saved file.
|
|
197
202
|
|
|
203
|
+
### DataLoader
|
|
204
|
+
- `ne.DataLoader(x, y, dtype=None, batch_size=32, shuffle=True, seed=None, bar=30)`: Create a data loader for batching and shuffling datasets during training and evaluation.
|
|
205
|
+
- Supports lists, tuples, numpy arrays, pandas dataframes and tensors as input data.
|
|
206
|
+
- Provides batching, shuffling, and progress bar display during iteration.
|
|
207
|
+
- Extensible for custom data loading strategies.
|
|
208
|
+
|
|
198
209
|
### Utilities
|
|
199
210
|
- Tensor creation: `tensor(data, requires_grad=False)`, `zeros(shape)`, `ones(shape)`, `rand(shape)`, `randn(shape, xavier=False)`, `randint(low, high, shape)` and their `_like` variants for matching shapes.
|
|
200
211
|
- Tensor operations: `sum`, `max`, `min`, `mean`, `var`, `log`, `sqrt`, `exp`, `abs`, `concat`, `stack`, `where`, `clip`, `array(data, dtype=...)` for elementwise, reduction, and conversion operations.
|
|
@@ -205,8 +216,9 @@ NeuralEngine is designed for easy extension and customization:
|
|
|
205
216
|
- **Custom Layers**: Create new layers by inheriting from the `Layer` base class and implementing the `forward(self, x)` method. You can add parameters, initialization logic, and custom computations as needed. All built-in layers follow this pattern, making it simple to add your own.
|
|
206
217
|
- **Custom Losses**: Define new loss functions by inheriting from the `Loss` base class and implementing the `compute(self, z, y)` method. This allows you to integrate any custom loss logic with autograd support.
|
|
207
218
|
- **Custom Optimizers**: Implement new optimization algorithms by inheriting from the `Optimizer` base class and providing your own `step(self)` method. You can manage optimizer state and parameter updates as required.
|
|
208
|
-
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method.
|
|
209
|
-
-
|
|
219
|
+
- **Custom Metrics**: Add new metrics by inheriting from the `Metric` base class and implementing the `compute(self, z, y)` method. This allows you to track any performance measure with metric accumulation.
|
|
220
|
+
- **Custom DataLoaders**: Extend the `DataLoader` class to create specialized data loading strategies. Override the `__getitem__` method to define how batches are constructed.
|
|
221
|
+
- All core components are modular and can be replaced or extended for research or production use.
|
|
210
222
|
|
|
211
223
|
## Contribution Guide
|
|
212
224
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import neuralengine.config as cf
|
|
2
|
+
from ..tensor import Tensor
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class DataLoader:
|
|
6
|
+
"""Data loader class for batching and shuffling data."""
|
|
7
|
+
def __init__(self, x, y, dtype=None, batch_size: int = 32, shuffle: bool = True, seed: int = None, bar: int = 30):
|
|
8
|
+
"""
|
|
9
|
+
@param x: Input data (array-like).
|
|
10
|
+
@param y: Target data (array-like).
|
|
11
|
+
@param dtype: Data type for the dataset.
|
|
12
|
+
@param batch_size: Number of samples per batch.
|
|
13
|
+
@param shuffle: Whether to shuffle the data at the start of each epoch.
|
|
14
|
+
@param seed: Seed for random number generator to ensure reproducibility.
|
|
15
|
+
@param bar: Length of the progress bar.
|
|
16
|
+
"""
|
|
17
|
+
self.x = Tensor(x, dtype=dtype)
|
|
18
|
+
self.y = Tensor(y, dtype=dtype)
|
|
19
|
+
self.batch_size = batch_size
|
|
20
|
+
self.shuffle = shuffle
|
|
21
|
+
self.current_batch = 0
|
|
22
|
+
self.num_samples = self.x.shape[0]
|
|
23
|
+
self.num_batches = (self.num_samples + batch_size - 1) // batch_size
|
|
24
|
+
self.indices = cf.nu.arange(self.num_samples)
|
|
25
|
+
self.rng = cf.nu.random.RandomState(seed)
|
|
26
|
+
self.bar = bar
|
|
27
|
+
|
|
28
|
+
def __len__(self) -> int:
|
|
29
|
+
"""Returns the number of batches."""
|
|
30
|
+
return self.num_batches
|
|
31
|
+
|
|
32
|
+
def __getitem__(self, index: int | slice) -> tuple[Tensor, Tensor]:
|
|
33
|
+
"""Gets a batch of data by index. Override for custom behavior."""
|
|
34
|
+
return self.x[index], self.y[index]
|
|
35
|
+
|
|
36
|
+
def __iter__(self) -> 'DataLoader':
|
|
37
|
+
"""Returns an iterator over the batches."""
|
|
38
|
+
self.current_batch = 0
|
|
39
|
+
if self.shuffle:
|
|
40
|
+
self.rng.shuffle(self.indices)
|
|
41
|
+
return self
|
|
42
|
+
|
|
43
|
+
def __next__(self) -> tuple[Tensor, Tensor]:
|
|
44
|
+
"""Returns the next batch of data."""
|
|
45
|
+
if self.current_batch < self.num_batches:
|
|
46
|
+
start_idx = self.current_batch * self.batch_size
|
|
47
|
+
end_idx = min(start_idx + self.batch_size, self.num_samples)
|
|
48
|
+
batch_indices = self.indices[start_idx:end_idx]
|
|
49
|
+
batch_data = self[batch_indices]
|
|
50
|
+
self.current_batch += 1
|
|
51
|
+
return batch_data
|
|
52
|
+
else:
|
|
53
|
+
raise StopIteration
|
|
54
|
+
|
|
55
|
+
def __repr__(self) -> str:
|
|
56
|
+
"""String representation showing progress bar."""
|
|
57
|
+
percent = (self.current_batch / self.num_batches) * 100
|
|
58
|
+
filled = int(self.bar * self.current_batch // self.num_batches)
|
|
59
|
+
progress = '█' * filled + '-' * (self.bar - filled)
|
|
60
|
+
return f"\r|{progress}| {percent:.0f}%"
|
|
@@ -5,7 +5,8 @@ from ..utils import *
|
|
|
5
5
|
class Loss:
|
|
6
6
|
"""Base class for all loss functions."""
|
|
7
7
|
def __init__(self):
|
|
8
|
-
self.loss_val =
|
|
8
|
+
self.loss_val = 0
|
|
9
|
+
self.count = 0
|
|
9
10
|
|
|
10
11
|
def __call__(self, z, y, *args, **kwargs):
|
|
11
12
|
""" Calls the loss compute method with the provided predictions and targets.
|
|
@@ -16,17 +17,23 @@ class Loss:
|
|
|
16
17
|
y = y if isinstance(y, Tensor) else Tensor(y)
|
|
17
18
|
loss = self.compute(z, y, *args, **kwargs)
|
|
18
19
|
|
|
19
|
-
self.loss_val
|
|
20
|
+
self.loss_val += loss.data.mean() if isinstance(loss, Tensor) else loss
|
|
21
|
+
self.count += 1
|
|
20
22
|
return loss
|
|
21
23
|
|
|
22
24
|
def __repr__(self) -> str:
|
|
23
25
|
""" Returns a string representation of the loss with its value if computed. """
|
|
24
|
-
if self.
|
|
25
|
-
return f"{self.__class__.__name__}: {self.loss_val:.4f}"
|
|
26
|
+
if self.count > 0:
|
|
27
|
+
return f"{self.__class__.__name__}: {(self.loss_val / self.count):.4f}"
|
|
26
28
|
else:
|
|
27
29
|
return "No loss computed yet."
|
|
28
30
|
|
|
29
|
-
def
|
|
31
|
+
def reset(self) -> None:
|
|
32
|
+
""" Resets the accumulated loss value and count. """
|
|
33
|
+
self.loss_val = 0
|
|
34
|
+
self.count = 0
|
|
35
|
+
|
|
36
|
+
def compute(self, z, y, *args, **kwargs) -> Tensor:
|
|
30
37
|
""" Computes the loss given predictions and targets. To be implemented by subclasses. """
|
|
31
38
|
raise NotImplementedError("compute() must be implemented in subclasses")
|
|
32
39
|
|
|
@@ -64,9 +71,8 @@ class Huber(Loss):
|
|
|
64
71
|
|
|
65
72
|
def compute(self, z, y):
|
|
66
73
|
# Huber: if |z - y| <= δ: 1/2 (z - y)² else: δ(|z - y| - 1/2 δ)
|
|
67
|
-
diff = z - y
|
|
68
|
-
|
|
69
|
-
loss = where(abs_diff <= self.delta, 0.5 * diff ** 2, self.delta * (abs_diff - 0.5 * self.delta))
|
|
74
|
+
diff = abs(z - y)
|
|
75
|
+
loss = where(diff <= self.delta, 0.5 * diff ** 2, self.delta * (diff - 0.5 * self.delta))
|
|
70
76
|
return mean(loss, axis=-1, keepdims=False)
|
|
71
77
|
|
|
72
78
|
|
|
@@ -5,7 +5,8 @@ from ..tensor import array
|
|
|
5
5
|
class Metric:
|
|
6
6
|
"""Base class for all metrics."""
|
|
7
7
|
def __init__(self):
|
|
8
|
-
self.metric_val =
|
|
8
|
+
self.metric_val = {}
|
|
9
|
+
self.count = 0
|
|
9
10
|
|
|
10
11
|
def __call__(self, z, y, *args, **kwargs):
|
|
11
12
|
""" Calls the metric compute method with the provided predictions and targets.
|
|
@@ -14,28 +15,40 @@ class Metric:
|
|
|
14
15
|
"""
|
|
15
16
|
z = z if isinstance(z, cf.nu.ndarray) else array(z)
|
|
16
17
|
y = y if isinstance(y, cf.nu.ndarray) else array(y)
|
|
17
|
-
|
|
18
|
+
metric = self.compute(z, y, *args, **kwargs)
|
|
18
19
|
|
|
19
|
-
if not isinstance(
|
|
20
|
+
if not isinstance(metric, dict):
|
|
20
21
|
raise ValueError("Metric compute method must return a dictionary.")
|
|
21
22
|
|
|
22
|
-
self.metric_val = metric_val
|
|
23
|
-
|
|
23
|
+
self.metric_val = {key: self.metric_val.get(key, 0) + value for key, value in metric.items()}
|
|
24
|
+
self.count += 1
|
|
25
|
+
return self
|
|
26
|
+
|
|
27
|
+
def __getitem__(self, key: str):
|
|
28
|
+
""" Allows access to individual metric values by key. """
|
|
29
|
+
return self.metric_val.get(key, None)
|
|
24
30
|
|
|
25
31
|
def __repr__(self) -> str:
|
|
26
32
|
""" Returns a string representation of the metric with its value if computed. """
|
|
27
|
-
if self.
|
|
28
|
-
|
|
33
|
+
if self.count > 0:
|
|
29
34
|
metric_str = ""
|
|
30
35
|
for key, value in self.metric_val.items():
|
|
31
|
-
if value is None: continue
|
|
32
36
|
if isinstance(value, (cf.nu.ndarray)) and value.ndim == 1:
|
|
33
37
|
value = value.mean(keepdims=False)
|
|
34
|
-
metric_str += f"{key}: {value:.4f}, "
|
|
35
|
-
return metric_str[:-2]
|
|
38
|
+
metric_str += f"{key}: {(value / self.count):.4f}, "
|
|
39
|
+
return metric_str[:-2] # Remove trailing comma and space
|
|
36
40
|
|
|
37
41
|
else:
|
|
38
42
|
return "No metric computed yet."
|
|
43
|
+
|
|
44
|
+
def reset(self) -> None:
|
|
45
|
+
""" Resets the accumulated metric values and count. """
|
|
46
|
+
self.metric_val = {}
|
|
47
|
+
self.count = 0
|
|
48
|
+
|
|
49
|
+
def compute(self, z, y, *args, **kwargs) -> dict[str, float | cf.np.ndarray]:
|
|
50
|
+
""" Computes the metric given predictions and targets. To be implemented by subclasses. """
|
|
51
|
+
raise NotImplementedError("compute() must be implemented in subclasses")
|
|
39
52
|
|
|
40
53
|
|
|
41
54
|
class RMSE(Metric):
|
|
@@ -68,14 +81,13 @@ class R2(Metric):
|
|
|
68
81
|
|
|
69
82
|
class ClassificationMetrics(Metric):
|
|
70
83
|
"""Classification metrics: Accuracy, Precision, Recall, F1 Score, Confusion Matrix."""
|
|
71
|
-
def __init__(self, num_classes: int = None, acc: bool = True, prec: bool = False, rec: bool = False, f1: bool = False
|
|
84
|
+
def __init__(self, num_classes: int = None, acc: bool = True, prec: bool = False, rec: bool = False, f1: bool = False):
|
|
72
85
|
"""
|
|
73
86
|
@param num_classes: Number of classes for classification tasks.
|
|
74
87
|
@param acc: Whether to compute accuracy.
|
|
75
88
|
@param prec: Whether to compute precision.
|
|
76
89
|
@param rec: Whether to compute recall.
|
|
77
90
|
@param f1: Whether to compute F1 score.
|
|
78
|
-
@param cm: Whether to compute confusion matrix. Only for evaluation mode.
|
|
79
91
|
"""
|
|
80
92
|
super().__init__()
|
|
81
93
|
self.num_classes = num_classes
|
|
@@ -83,7 +95,6 @@ class ClassificationMetrics(Metric):
|
|
|
83
95
|
self.prec = prec
|
|
84
96
|
self.rec = rec
|
|
85
97
|
self.f1 = f1
|
|
86
|
-
self.cm = cm
|
|
87
98
|
|
|
88
99
|
def compute(self, z, y):
|
|
89
100
|
if self.num_classes is None:
|
|
@@ -100,28 +111,41 @@ class ClassificationMetrics(Metric):
|
|
|
100
111
|
FP = cf.nu.sum(cm, axis=0) - TP
|
|
101
112
|
FN = cf.nu.sum(cm, axis=1) - TP
|
|
102
113
|
|
|
103
|
-
acc, prec, rec, f1 = None, None, None, None
|
|
114
|
+
acc, prec, rec, f1, metrics = None, None, None, None, {}
|
|
104
115
|
if self.acc:
|
|
105
116
|
# Accuracy = trace(cm) / sum(cm)
|
|
106
117
|
acc = cf.nu.trace(cm) / cf.nu.sum(cm) if cf.nu.sum(cm) > 0 else 0
|
|
118
|
+
metrics["Accuracy"] = acc
|
|
107
119
|
if self.prec:
|
|
108
120
|
# Precision = TP / (TP + FP)
|
|
109
121
|
prec = cf.nu.zeros_like(TP, dtype=cf.nu.float32)
|
|
110
122
|
cf.nu.divide(TP, TP + FP, out=prec, where=(TP + FP) != 0)
|
|
123
|
+
metrics["Precision"] = prec
|
|
111
124
|
if self.rec:
|
|
112
125
|
# Recall = TP / (TP + FN)
|
|
113
126
|
rec = cf.nu.zeros_like(TP, dtype=cf.nu.float32)
|
|
114
127
|
cf.nu.divide(TP, TP + FN, out=rec, where=(TP + FN) != 0)
|
|
128
|
+
metrics["Recall"] = rec
|
|
115
129
|
if self.f1:
|
|
116
130
|
# F1 = 2 * Precision * Recall / (Precision + Recall)
|
|
117
131
|
f1 = cf.nu.zeros_like(TP, dtype=cf.nu.float32)
|
|
118
132
|
cf.nu.divide(2 * prec * rec, prec + rec, out=f1, where=(prec + rec) != 0)
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
metrics["F1 Score"] = f1
|
|
134
|
+
return metrics
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class Perplexity(Metric):
|
|
138
|
+
"""Perplexity metric for generative models."""
|
|
139
|
+
def __init__(self, eps: float = 1e-7):
|
|
140
|
+
"""
|
|
141
|
+
@param eps: Small value for numerical stability
|
|
142
|
+
"""
|
|
143
|
+
super().__init__()
|
|
144
|
+
self.eps = eps
|
|
145
|
+
|
|
146
|
+
def compute(self, z, y):
|
|
147
|
+
# Perplexity = exp(-1/N Σ log(p(y|x)))
|
|
148
|
+
z = cf.nu.clip(z, self.eps, 1 - self.eps)
|
|
149
|
+
log_likelihood = -cf.nu.sum(y * cf.nu.log(z), axis=-1)
|
|
150
|
+
perplexity = cf.nu.exp(cf.nu.mean(log_likelihood))
|
|
151
|
+
return {"Perplexity": perplexity}
|
|
@@ -2,10 +2,12 @@ import os
|
|
|
2
2
|
import pickle as pkl
|
|
3
3
|
import neuralengine.config as cf
|
|
4
4
|
from itertools import chain
|
|
5
|
-
from ..tensor import Tensor, NoGrad
|
|
5
|
+
from ..tensor import Tensor, NoGrad
|
|
6
|
+
from ..utils import concat
|
|
6
7
|
from .layers import Layer, Mode, Flatten, LSTM
|
|
7
8
|
from .optim import Optimizer
|
|
8
9
|
from .loss import Loss
|
|
10
|
+
from .dataload import DataLoader
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class Model:
|
|
@@ -13,15 +15,13 @@ class Model:
|
|
|
13
15
|
Allows for defining the model architecture, optimizer, loss function, and metrics.
|
|
14
16
|
The model can be trained and evaluated.
|
|
15
17
|
"""
|
|
16
|
-
|
|
17
18
|
def __init__(self, input_size: tuple | int, optimizer: Optimizer = None, loss: Loss = None, metrics=()):
|
|
18
19
|
"""
|
|
19
20
|
@param input_size: Tuple or int, shape of input data samples (int if 1D).
|
|
20
21
|
@param optimizer: Optimizer instance.
|
|
21
22
|
@param loss: Loss instance.
|
|
22
|
-
@param metrics: List/tuple of Metric or Loss instances
|
|
23
|
+
@param metrics: List/tuple of Metric or Loss instances.
|
|
23
24
|
"""
|
|
24
|
-
|
|
25
25
|
self.input_size = input_size
|
|
26
26
|
|
|
27
27
|
if not isinstance(optimizer, Optimizer):
|
|
@@ -48,7 +48,6 @@ class Model:
|
|
|
48
48
|
Builds the model by adding layers.
|
|
49
49
|
@param layers: Variable number of Layer instances to add to the model.
|
|
50
50
|
"""
|
|
51
|
-
|
|
52
51
|
self.parameters, prevLayer = {}, None
|
|
53
52
|
for i, layer in enumerate(layers):
|
|
54
53
|
|
|
@@ -73,12 +72,12 @@ class Model:
|
|
|
73
72
|
layer.in_size = self.input_size
|
|
74
73
|
self.input_size = layer.out_size if hasattr(layer, 'out_size') else self.input_size
|
|
75
74
|
if isinstance(layer, Flatten):
|
|
76
|
-
self.input_size = int(cf.
|
|
75
|
+
self.input_size = int(cf.np.prod(self.input_size))
|
|
77
76
|
|
|
78
77
|
self.parameters[f"layer_{i}"] = list(layer.parameters()) # Collect parameters from the layer
|
|
79
78
|
|
|
80
79
|
self.layers = layers
|
|
81
|
-
self.optimizer.parameters = list(chain
|
|
80
|
+
self.optimizer.parameters = list(chain(*self.parameters.values()))
|
|
82
81
|
|
|
83
82
|
|
|
84
83
|
@classmethod
|
|
@@ -141,110 +140,87 @@ class Model:
|
|
|
141
140
|
else: pkl.dump(self, file)
|
|
142
141
|
|
|
143
142
|
|
|
144
|
-
def train(self,
|
|
143
|
+
def train(self, dataloader: DataLoader, epochs: int = 10, ckpt_interval: int = None) -> None:
|
|
145
144
|
"""
|
|
146
145
|
Trains the model on data.
|
|
147
|
-
@param
|
|
148
|
-
@param
|
|
149
|
-
@param epochs: Number of epochs
|
|
150
|
-
@param batch_size: Batch size (None for full batch)
|
|
151
|
-
@param seed: Seed for random shuffling
|
|
146
|
+
@param dataloader: DataLoader instance providing training data.
|
|
147
|
+
@param epochs: Number of epochs to train
|
|
152
148
|
@param ckpt_interval: Interval (in epochs) to save checkpoints
|
|
153
149
|
"""
|
|
150
|
+
if not isinstance(dataloader, DataLoader):
|
|
151
|
+
raise ValueError("dataloader must be an instance of DataLoader class")
|
|
154
152
|
|
|
155
153
|
for layer in self.layers:
|
|
156
154
|
layer.mode = Mode.TRAIN
|
|
157
155
|
|
|
158
|
-
x, y = array(x), array(y)
|
|
159
|
-
|
|
160
|
-
if batch_size is None:
|
|
161
|
-
batch_size = x.shape[0]
|
|
162
|
-
if batch_size <= 0 or batch_size > x.shape[0]:
|
|
163
|
-
raise ValueError("batch_size must be a positive integer ≤ number of samples")
|
|
164
|
-
|
|
165
156
|
for i in range(epochs):
|
|
166
157
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
shuffle_indices = cf.nu.random.permutation(x.shape[0])
|
|
170
|
-
x, y = x[shuffle_indices], y[shuffle_indices] # Shuffle data
|
|
171
|
-
|
|
172
|
-
for j in range(0, x.shape[0], batch_size):
|
|
173
|
-
x_batch = x[j:j + batch_size]
|
|
174
|
-
y_batch = y[j:j + batch_size]
|
|
158
|
+
for batch in dataloader:
|
|
159
|
+
x, y = batch
|
|
175
160
|
|
|
176
161
|
# Forward pass
|
|
177
162
|
for layer in self.layers:
|
|
178
|
-
|
|
163
|
+
x = layer(x)
|
|
179
164
|
# For stacked LSTM, pass outputs accordingly
|
|
180
|
-
if isinstance(layer, LSTM):
|
|
165
|
+
if isinstance(layer, LSTM): x = x[layer.use_output[0]]
|
|
181
166
|
|
|
182
|
-
# Compute loss
|
|
183
|
-
loss = self.loss(x_batch, y_batch)
|
|
184
|
-
loss_val += self.loss.loss_val
|
|
185
|
-
|
|
167
|
+
loss = self.loss(x, y) # Compute loss
|
|
186
168
|
loss.backward() # Backward pass
|
|
187
169
|
|
|
188
170
|
# Compute metrics
|
|
189
171
|
for metric in self.metrics:
|
|
190
|
-
|
|
191
|
-
if isinstance(metric, Loss):
|
|
192
|
-
key = metric.__class__.__name__
|
|
193
|
-
metric_vals[key] = metric_vals.get(key, 0.0) + metric.loss_val
|
|
194
|
-
continue
|
|
195
|
-
for key, value in metric_val.items():
|
|
196
|
-
if value is None: continue
|
|
197
|
-
metric_vals[key] = metric_vals.get(key, 0.0) + value
|
|
172
|
+
metric(x, y)
|
|
198
173
|
|
|
199
174
|
# Update parameters
|
|
200
175
|
self.optimizer.step()
|
|
201
176
|
self.optimizer.reset_grad() # Reset gradients
|
|
202
177
|
|
|
203
|
-
|
|
204
|
-
output_strs = [f"Epoch {i + 1}/{epochs}", f"Loss: {loss_val:.4f}"]
|
|
178
|
+
print(dataloader, f'Epoch {i + 1}/{epochs}', sep=', ', end='', flush=True) # Show progress bar
|
|
205
179
|
|
|
206
|
-
|
|
207
|
-
value /= (x.shape[0] / batch_size) # Average metric over batches
|
|
208
|
-
if isinstance(value, (cf.nu.ndarray)) and value.ndim == 1:
|
|
209
|
-
value = value.mean(keepdims=False)
|
|
210
|
-
output_strs.append(f"{key}: {value:.4f}")
|
|
180
|
+
output_strs = [f": (Loss) {self.loss}", *self.metrics]
|
|
211
181
|
|
|
212
182
|
# Save checkpoint
|
|
213
183
|
if ckpt_interval and (i + 1) % ckpt_interval == 0:
|
|
214
184
|
self.save(f"checkpoints/model_epoch_{i + 1}.pkl", weights_only=True)
|
|
215
185
|
output_strs.append("Checkpoint saved")
|
|
186
|
+
print(*output_strs, sep=', ', flush=True)
|
|
216
187
|
|
|
217
|
-
|
|
188
|
+
# Reset loss and metrics for next epoch
|
|
189
|
+
self.loss.reset()
|
|
190
|
+
for metric in self.metrics: metric.reset()
|
|
218
191
|
|
|
219
192
|
|
|
220
|
-
def eval(self,
|
|
193
|
+
def eval(self, dataloader: DataLoader) -> Tensor:
|
|
221
194
|
"""
|
|
222
195
|
Evaluates the model on data.
|
|
223
|
-
@param
|
|
224
|
-
@param y: Target data, shape (N, target_features)
|
|
196
|
+
@param dataloader: DataLoader instance providing evaluation data.
|
|
225
197
|
@return: Output tensor after evaluation
|
|
226
198
|
"""
|
|
199
|
+
if not isinstance(dataloader, DataLoader):
|
|
200
|
+
raise ValueError("dataloader must be an instance of DataLoader class")
|
|
227
201
|
|
|
228
202
|
for layer in self.layers:
|
|
229
203
|
layer.mode = Mode.EVAL
|
|
230
204
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
print(
|
|
250
|
-
|
|
205
|
+
z = []
|
|
206
|
+
for batch in dataloader:
|
|
207
|
+
x, y = batch
|
|
208
|
+
|
|
209
|
+
# Forward pass
|
|
210
|
+
with NoGrad():
|
|
211
|
+
for layer in self.layers:
|
|
212
|
+
x = layer(x)
|
|
213
|
+
# For stacked LSTM, pass outputs accordingly
|
|
214
|
+
if isinstance(layer, LSTM): x = x[layer.use_output[0]]
|
|
215
|
+
|
|
216
|
+
z.append(x) # Accumulate outputs
|
|
217
|
+
self.loss(x, y) # Compute loss
|
|
218
|
+
|
|
219
|
+
# Compute metrics
|
|
220
|
+
for metric in self.metrics:
|
|
221
|
+
metric(x, y)
|
|
222
|
+
|
|
223
|
+
print(dataloader, 'Evaluation', sep=', ', end='', flush=True) # Show progress bar
|
|
224
|
+
|
|
225
|
+
print(f": (Loss) {self.loss}", *self.metrics, sep=', ', flush=True)
|
|
226
|
+
return concat(*z, axis=0)
|
|
@@ -43,7 +43,6 @@ class SGD(Optimizer):
|
|
|
43
43
|
@param momentum: Momentum factor
|
|
44
44
|
@param nesterov: Use Nesterov momentum
|
|
45
45
|
"""
|
|
46
|
-
|
|
47
46
|
super().__init__()
|
|
48
47
|
self.lr = lr
|
|
49
48
|
self.reg = reg
|
|
@@ -83,7 +82,6 @@ class Adam(Optimizer):
|
|
|
83
82
|
@param eps: Numerical stability
|
|
84
83
|
@param reg: L2 regularization
|
|
85
84
|
"""
|
|
86
|
-
|
|
87
85
|
super().__init__()
|
|
88
86
|
self.lr = lr
|
|
89
87
|
betas = betas if isinstance(betas, (list, tuple)) else (betas,)
|
|
@@ -105,7 +103,6 @@ class Adam(Optimizer):
|
|
|
105
103
|
Updates the parameters using Adam optimization algorithm.
|
|
106
104
|
RMSProp algorithm is used if only one beta is provided.
|
|
107
105
|
"""
|
|
108
|
-
|
|
109
106
|
self.t += 1
|
|
110
107
|
for param in self._params:
|
|
111
108
|
# grad = ∂L/∂w + λw (L2 regularization)
|
|
@@ -758,6 +758,8 @@ def array(data, dtype=cf.nu.float32):
|
|
|
758
758
|
@param dtype: Desired data type of the output array.
|
|
759
759
|
"""
|
|
760
760
|
if isinstance(data, Tensor):
|
|
761
|
+
if dtype is None:
|
|
762
|
+
return data.data.copy()
|
|
761
763
|
return data.data.astype(dtype)
|
|
762
764
|
return cf.nu.asarray(data, dtype=dtype)
|
|
763
765
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "NeuralEngine"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.7"
|
|
8
8
|
description = "A framework/library for building and training neural networks."
|
|
9
9
|
authors = [
|
|
10
10
|
{ name = "Prajjwal Pratap Shah", email = "prajjwalpratapshah@outlook.com" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|