Building Neural Networks from scratch.
Project description
NN-Without-Frameworks
This project aims to implement different Neural Network configuration without using scientific frameworks like TensorFlow or PyTorch.
Each network/config is implemented in 4 formats while trying to get the best of both worlds of TensorFlow (+ Keras) and PyTorch :
- In Python using NumPy
- In Python without taking advantage of NumPy
- In java
- In C++
What is currently supported? (equally in all languages and formats)
Layers:
- Fully Connected
Activations:
- Linear
- ReLU
Loss functions:
- MSE
- Cross Entropy
Weight Initializers:
- Xavier Uniform (aka Glorot)
- He Normal (aka Kaiming Normal)
bias initializer:
- Constant (zero)
Optimizers:
- SGD
- SGD + Momentum
- RMSProp
- AdaGrad
- Adam
Regularizer:
- l1
- l2
Normalization:
- BatchNorm1d
Examples
Each directory contains a train.* that performs tests of correctness and functionality according to its corresponding format and language. You can run it to get a sense of what is going on.
Snippet
Define your network
- Python:
from nn_without_frameworks import numpy_nn as nn # from nn_without_frameworks import pure_nn as nn
class MyNet(nn.Module):
def __init__(self, input_dim, out_dim):
super().__init__()
self.input_dim = input_dim
self.out_dim = out_dim
self.hidden1 = nn.layers.Dense(in_features=self.input_dim,
out_features=100,
activation=nn.acts.ReLU(),
weight_initializer=nn.inits.HeNormal(nn.acts.ReLU()),
bias_initializer=nn.inits.Constant(0.),
regularizer_type="l2",
lam=1e-3
)
self.output = nn.layers.Dense(in_features=100,
out_features=self.out_dim,
weight_initializer=nn.inits.XavierUniform(),
bias_initializer=nn.inits.Constant(0.),
regularizer_type="l2",
lam=1e-3
)
def forward(self, x):
x = self.hidden1(x)
return self.output(x)
- Java:
import Layers.Dense;
class MyNet extends Module{
int in_features = 0, out_features = 0;
Dense hidden1, output;
public MyNet(int in_features, int out_features){
this.in_features = in_features;
this.out_features = out_features;
this.hidden1 = new Dense(this.in_features,
100,
"relu",
"he_normal",
"zeros", // bias initializer
"l2",
0.001F);
this.layers.add(this.hidden1); // the Crucial and only different part to PyTorch's subclassing
this.output = new Dense(100,
out_features,
"linear",
"xavier_uniform",
"zeros", // bias initializer
"l2",
0.001F);
this.layers.add(this.output); // Crucial and different part to PyTorch's subclassing
}
public float[][] forward(float[][] x){
x = this.hidden1.forward(x);
x = this.output.forward(x);
return x;
}
}
- C++:
#include <iostream>
#include <module.h>
#include <layers.h>
using namespace std;
class MyNet : public Module{
public:
int in_features = 0, out_features = 0;
Dense *hidden, *output; // Layers should be predifned especially, they should be pointers
MyNet(int in_features, int out_features){
this->in_features = in_features;
this->out_features = out_features;
this->hidden = new Dense{this->in_features,
100,
"relu",
"he_normal",
"zeros", // bias initializer
"l2",
0.001};
this->parameters.push_back(this->hidden); // same as java
this->output = new Dense{100,
this->out_features,
"linear",
"xavier_uniform",
"zeros", // bias initializer
"l2",
0.001};
this->parameters.push_back(this->output); same as java
}
float_batch forward(const float_batch &input){ // float_batch =: vector<vector<float> >
float_batch x = this->hidden->forward(input);
x = this->output->forward(x);
return x;
}
};
Train your network
- Python
my_net = MyNet(num_features, num_classes)
ce_loss = nn.losses.CrossEntropyLoss()
opt = nn.optims.SGD(my_net.parameters, lr=1.)
for step in range(epoch):
y = my_net(x)
loss = ce_loss(y, t)
my_net.backward(loss)
opt.apply()
- Java:
import Losses.*;
import Optimizers.*;
MyNet my_net = new MyNet(num_features, num_classes);
CrossEntropyLoss celoss = new CrossEntropyLoss();
SGD opt = new SGD(1.0F, my_net.layers);
for (int epoch = 0; epoch < num_epoch; epoch++) {
y = my_net.forward(x);
Loss loss = celoss.apply(y, t);
my_net.backward(loss);
opt.apply();
}
- C++:
#include <losses.h>
#include <optimizers.h>
MyNet my_net = MyNet{num_features, num_classes};
CrossEntropyLoss celoss;
SGD opt(1, my_net.parameters);
float_batch y; // float_batch =: vector<vector<float> >
for(int step = 0; step < num_epoch; step++){
y= my_net.forward(x);
Loss loss = celoss.apply(y, t);
my_net.backward(loss);
opt.apply();
}
Acknowledgement
- Current code is inspired by the elegant and simple repository Simple Neural Networks by @MorvanZhou .
- Mathematical foundation of different parts is based on slides of CS W182 / 282A and CS231n courses.
Contributing
- The current code is far from done and any fix, suggestion, pull request, issue, etc is highly appreciated and welcome. 🤗
- Current work focuses on discovering what is under the hood rather optimization involved in implementing ideas so, feel free to conduct sanity-checks behind the math and correctness of each part and/or if you come up with a better or optimized solution, please don't hesitate to bring up a PR. [thank you in advance. 😊]
- You can take a look at
todo.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nn_without_frameworks-0.1.3.tar.gz.
File metadata
- Download URL: nn_without_frameworks-0.1.3.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/4.8.2 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b71237491a7b6968449f4c24da74f53919cac18e02910c88495a876fa2fc421e
|
|
| MD5 |
5a30c2046ffe700a4006b11c10b0bc4f
|
|
| BLAKE2b-256 |
62547f5621af598ec2bddad49c76e1067901ac1a26211ca33d0c8c2ae3496510
|
File details
Details for the file nn_without_frameworks-0.1.3-py3-none-any.whl.
File metadata
- Download URL: nn_without_frameworks-0.1.3-py3-none-any.whl
- Upload date:
- Size: 27.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.7.1 importlib_metadata/4.8.2 pkginfo/1.8.2 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5f2f4cceb1d42f525c5a57bc9a838b68a5d0d179a9d44a58716de86b77442de
|
|
| MD5 |
85014164b7a0dd6b8a87588b5f28e4db
|
|
| BLAKE2b-256 |
5879fb66390b46ca7fa4485a33e40d1a959a63abcb1730bc5b3ba8723c90a643
|