From f315feae5f09567d7abefb15cf35ff48aca3148a Mon Sep 17 00:00:00 2001 From: "szewczyk.franciszek02" Date: Wed, 8 Nov 2023 21:51:22 +0100 Subject: [PATCH] README update --- README.md | 53 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 9d2a109..1b1e9cf 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,18 @@ It supports multiple optimizers, such as Adam or SGD, all the most common activa ## Usage -Make sure your compiler supports C++17. Shkyera Grad is a header-only library, so the only thing you need to do is to include it in your project. +Check out oour [Get Started Guide](https://fszewczyk.github.io/shkyera-grad/md_docs_tutorials_GetStarted.html) to learn the basics of _Shkyera Engine_. -```cpp -#include "include/ShkyeraGrad.hpp" -``` +## Showcase -Check out the [examples](examples/README.md) for a quick start on Shkyera Grad. In the meantime, here's a neural network that learns the XOR function. +Here's a small example showcasing a feed-forward network learning the XOR function. Check out the `examples/` folder for more examples. ```cpp -#include "include/ShkyeraGrad.hpp" +#include "shkyera-grad/include/ShkyeraGrad.hpp" int main() { using namespace shkyera; + using T = Type::float32; std::vector xs; std::vector ys; @@ -41,31 +40,39 @@ int main() { 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({0, 0})); ys.push_back(Vec32::of({0})); + xs.push_back(Vec32::of({1, 1})); ys.push_back(Vec32::of({0})); - auto mlp = SequentialBuilder::begin() - .add(Layer32::create(2, 15, Activation::relu)) - .add(Layer32::create(15, 5, Activation::relu)) - .add(Layer32::create(5, 1, Activation::sigmoid)) - .build(); + auto network = SequentialBuilder::begin() + .add(Linear32::create(2, 15)) + .add(ReLU32::create()) + .add(Linear32::create(15, 5)) + .add(ReLU32::create()) + .add(Linear32::create(5, 1)) + .add(Sigmoid32::create()) + .build(); - Optimizer32 optimizer = Optimizer(mlp->parameters(), 0.1); - Loss::Function32 lossFunction = Loss::MSE; + auto optimizer = Adam32(network->parameters(), 0.05); + auto lossFunction = Loss::MSE; - // ------ TRAINING THE NETWORK ------- // - for (size_t epoch = 0; epoch < 100; epoch++) { + for (size_t epoch = 0; epoch < 100; epoch++) { // We train for 100 epochs auto epochLoss = Val32::create(0); - optimizer.reset(); - for (size_t sample = 0; sample < xs.size(); ++sample) { - Vec32 pred = mlp->forward(xs[sample]); - auto loss = lossFunction(pred, ys[sample]); + 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; + epochLoss = epochLoss + loss; // Store the loss for feedback } - optimizer.step(); + optimizer.step(); // Update the parameters + + auto averageLoss = epochLoss / Val32::create(xs.size()); + std::cout << "Epoch: " << epoch + 1 << " Loss: " << averageLoss->getValue() << std::endl; + } - std::cout << "Epoch: " << epoch + 1 << " Loss: " << epochLoss->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; } } ```