Skip to content

Commit

Permalink
Updated example and README
Browse files Browse the repository at this point in the history
  • Loading branch information
fszewczyk committed Nov 9, 2023
1 parent a40b76d commit d4debfb
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 25 deletions.
40 changes: 20 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,17 @@ int main() {
using namespace shkyera;
using T = Type::float32;

std::vector<Vec32> xs;
std::vector<Vec32> ys;

// ---------- INPUT ----------- | -------- OUTPUT --------- //
xs.push_back(Vec32::of(0, 0)); ys.push_back(Vec32::of(0));
xs.push_back(Vec32::of(1, 0)); ys.push_back(Vec32::of(1));
xs.push_back(Vec32::of(0, 1)); ys.push_back(Vec32::of(1));
xs.push_back(Vec32::of(1, 1)); ys.push_back(Vec32::of(0));
// This is our XOR dataset. It maps from Vec32 to Vec32
Dataset<Vec32, Vec32> data;
data.addSample(Vec32::of(0, 0), Vec32::of(0));
data.addSample(Vec32::of(0, 1), Vec32::of(1));
data.addSample(Vec32::of(1, 0), Vec32::of(1));
data.addSample(Vec32::of(1, 1), Vec32::of(0));

// The is the data loader, it will take care of batching
size_t batchSize = 2;
bool shuffle = true;
DataLoader loader(data, batchSize, shuffle);

auto network = SequentialBuilder<Type::float32>::begin()
.add(Linear32::create(2, 15))
Expand All @@ -52,29 +55,26 @@ int main() {
.add(Sigmoid32::create())
.build();


auto optimizer = Adam32(network->parameters(), 0.05);
auto optimizer = Adam32(network->parameters(), 0.1);
auto lossFunction = Loss::MSE<T>;

for (size_t epoch = 0; epoch < 100; epoch++) { // We train for 100 epochs
auto epochLoss = Val32::create(0);

optimizer.reset(); // Reset the gradients
for (size_t sample = 0; sample < xs.size(); ++sample) { // We go through each sample
Vec32 pred = network->forward(xs[sample]); // We get some prediction
auto loss = lossFunction(pred, ys[sample]); // And calculate its error

epochLoss = epochLoss + loss; // Store the loss for feedback
optimizer.reset(); // Reset the gradients
for (const auto &[x, y] : loader) { // For each batch
auto pred = network->forward(x); // We get some prediction
epochLoss = epochLoss + Loss::compute(lossFunction, pred, y); // And calculate its error
}
optimizer.step(); // Update the parameters

auto averageLoss = epochLoss / Val32::create(xs.size());
auto averageLoss = epochLoss / Val32::create(loader.getTotalBatches());
std::cout << "Epoch: " << epoch + 1 << " Loss: " << averageLoss->getValue() << std::endl;
}

for (size_t sample = 0; sample < xs.size(); ++sample) { // Go through each example
Vec32 pred = network->forward(xs[sample]); // Predict result
std::cout << xs[sample] << " -> " << pred[0] << "\t| True: " << ys[sample][0] << std::endl;
for (auto &[x, y] : data) { // Go through each example
auto pred = network->forward(x); // We get some prediction
std::cout << x << " -> " << pred[0] << "\t| True: " << y[0] << std::endl;
}
}
```
15 changes: 10 additions & 5 deletions examples/xor_regression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ int main() {
using T = Type::float32;

// clang-format off
// This is our XOR dataset. It maps from Vec32 to Vec32
Dataset<Vec32, Vec32> data;

data.addSample(Vec32::of(0, 0), Vec32::of(0));
data.addSample(Vec32::of(0, 1), Vec32::of(1));
data.addSample(Vec32::of(1, 0), Vec32::of(1));
data.addSample(Vec32::of(1, 1), Vec32::of(0));

// The is the data loader, it will take care of batching
size_t batchSize = 2;
bool shuffle = true;
DataLoader loader(data, batchSize, shuffle);

auto network = SequentialBuilder<Type::float32>::begin()
.add(Linear32::create(2, 15))
.add(ReLU32::create())
Expand All @@ -22,20 +27,20 @@ int main() {
.build();
// clang-format on

auto optimizer = Adam32(network->parameters(), 0.05);
auto optimizer = Adam32(network->parameters(), 0.1);
auto lossFunction = Loss::MSE<T>;

for (size_t epoch = 0; epoch < 100; epoch++) { // We train for 100 epochs
auto epochLoss = Val32::create(0);

optimizer.reset(); // Reset the gradients
for (auto &[x, y] : data) {
optimizer.reset(); // Reset the gradients
for (const auto &[x, y] : loader) { // For each batch
auto pred = network->forward(x); // We get some prediction
epochLoss = epochLoss + Loss::compute(lossFunction, pred, y); // And calculate its error
}
optimizer.step(); // Update the parameters

auto averageLoss = epochLoss / Val32::create(data.size());
auto averageLoss = epochLoss / Val32::create(loader.getTotalBatches());
std::cout << "Epoch: " << epoch + 1 << " Loss: " << averageLoss->getValue() << std::endl;
}

Expand Down
1 change: 1 addition & 0 deletions include/ShkyeraGrad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "nn/Neuron.hpp"
#include "nn/Sequential.hpp"

#include "nn/data/DataLoader.hpp"
#include "nn/data/Dataset.hpp"

#include "nn/optimizers/AdaMax.hpp"
Expand Down
2 changes: 2 additions & 0 deletions include/core/Utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ std::enable_if_t<std::is_integral_v<T>, std::vector<T>> sample(T from, T to, siz
return sampled;
}

template <typename T> void shuffle(std::vector<T> &vec) { std::shuffle(vec.begin(), vec.end(), rand_dev); }

template <typename Clock = std::chrono::high_resolution_clock> auto startTimer() { return Clock::now(); }

template <typename Clock = std::chrono::high_resolution_clock>
Expand Down

0 comments on commit d4debfb

Please sign in to comment.