From c7e87fe191249afe6b8a83c62943b3e4b3b25868 Mon Sep 17 00:00:00 2001 From: Michelle Date: Tue, 28 Jul 2026 19:36:26 +0200 Subject: [PATCH] model.cpp/hpp I made the model struct to store layers. I'm still missing the backward functions, but it's functional --- include/math/mul.hpp | 0 include/neural_network/layer/layer.hpp | 74 +++--- include/neural_network/layer/layer_dense.hpp | 93 +++++--- include/neural_network/model/model.hpp | 178 ++++++++++++++ include/random/seed.hpp | 8 - main.cpp | 21 ++ src/math/add.cpp | 3 +- src/math/mul.hpp | 0 src/neural_network/layer/layer_dense.cpp | 48 ++-- src/neural_network/model/model.cpp | 234 +++++++++++++++++++ 10 files changed, 552 insertions(+), 107 deletions(-) create mode 100644 include/math/mul.hpp create mode 100644 include/neural_network/model/model.hpp create mode 100644 src/math/mul.hpp create mode 100644 src/neural_network/model/model.cpp diff --git a/include/math/mul.hpp b/include/math/mul.hpp new file mode 100644 index 0000000..e69de29 diff --git a/include/neural_network/layer/layer.hpp b/include/neural_network/layer/layer.hpp index d8372a7..284e5c0 100644 --- a/include/neural_network/layer/layer.hpp +++ b/include/neural_network/layer/layer.hpp @@ -28,7 +28,7 @@ * Author: Michelle Bausager * * Description: - * Defines the base layers struct used in pther layers in neural network + * Defines the base layers struct used in other layers in neural network * *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #pragma once @@ -38,38 +38,57 @@ #include // panic::uint_t, panic::int_t, and panic::real_t #include // panic::tensor::real_matrix (uint_matrix, int_matrix) -//--------------------------------------------------------------------------------------------------------------------------- -// DEFINE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------------------------------- -// TYPE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- - -//--------------------------------------------------------------------------------------------------------------------------- -// Type Name : panic::neural_network::layer -// -// Description: -// A base layer to use in neural networks -// -// Member Variables: -// None. -// -// Notes: -// This base layer should be used in all layers/activations that have a forward and backward function -// This is done so it's easy to make a list of layers in the model to loop over. -// The virtual means it should use derived object's version when called with a pointer. -// The =0 means the derviced object NEEDS to have these functions to work. -// -//--------------------------------------------------------------------------------------------------------------------------- namespace panic{ namespace neural_network{ + + +/** + * @brief Base layer for the rest of the neural network library to use + * + * This base layer should be used in all layers/activations that have a forward and backward function + * This is done so it's easy to make a list of layers in the model to loop over. + * The virtual means it should use derived object's version when called with a pointer. + * The =0 means the derivative object NEEDS to have these functions to work. + * + * The struct is used for PANIC neural_network library. + */ struct layer{ + /** + * @brief Emphty output matrix to store layer output + * + * Output shape: + * samples x neuron_count + */ + panic::tensor::real_matrix outputs; + + /** + * @brief Default de-constructor + * + */ virtual ~layer() = default; + + /** + * @brief Virtual forward function for derivative layers + * + * @param inputs Data matrix input for forward function. + * + * @Note It's equal to 0 because it make the derivative + * object NEEDS to have these function to work. + */ virtual bool forward(const panic::tensor::real_matrix& inputs) = 0; + + /** + * @brief Virtual backward function for derivative layers + * + * @param dinputs Data matrix input for backward function. + * + * @Note It's equal to 0 because it make the derivative + * object NEEDS to have these function to work. + */ virtual bool backward(const panic::tensor::real_matrix& dinputs) = 0; }; @@ -79,12 +98,5 @@ struct layer{ } // namespace tensor } // namespace panic -//--------------------------------------------------------------------------------------------------------------------------- -// VARIABLE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- - -//--------------------------------------------------------------------------------------------------------------------------- -// FUNCTION PROTOTYPE -//--------------------------------------------------------------------------------------------------------------------------- diff --git a/include/neural_network/layer/layer_dense.hpp b/include/neural_network/layer/layer_dense.hpp index ed26e44..ff4600a 100644 --- a/include/neural_network/layer/layer_dense.hpp +++ b/include/neural_network/layer/layer_dense.hpp @@ -24,7 +24,7 @@ * Module Name: neural_network * File Name: layer_dense.hpp * Revision: 0.1.0 - * Date: 23-06-2026 + * Date: 28-08-2026 * Author: Michelle Bausager * * Description: @@ -41,59 +41,76 @@ #include #include -//--------------------------------------------------------------------------------------------------------------------------- -// DEFINE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------------------------------- -// TYPE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- - -//-------------------------------------------------------------------------------------------------------------------------- -// Function Name : panic::neural_network::layer_dense -// -// Description: -// Dense/fully-connected neural network layer. -// -// Inputs: -// Samples x input size const panic::tensor::real_matrix& -// -// Weight shape: -// input_size x neuron_count -// -// Bias shape: -// 1 x neuron_count -// -// Output shape: -// samples x neuron_count panic::tensor::real_matrix -// -// Notes: -// forward(input) calculates: -// -// outputs = inputs * weights + biases -//-------------------------------------------------------------------------------------------------------------------------- namespace panic{ namespace neural_network{ +/** + * @brief struct for dense layer object used in neural networks + * + * Computes: + * @code + * panic::neural_network::layer_dense myDenseLayer(3, 5); + * myDenseLayer.forward(inputMatrix); + * @endcode + * + * The struct is used in PANIC nural_network library. + */ struct layer_dense : public layer{ + /** + * @brief Emphty weight matrix to store layer weights + * + * Weight shape: + * input_size x neuron_count + */ panic::tensor::real_matrix weights; - panic::tensor::real_vector biases; - panic::tensor::real_matrix outputs; - // Empthy contructor + /** + * @brief Emphty bias vector to store layer bias + * + * Bias shape: + * 1 x neuron_count + */ + panic::tensor::real_vector biases; + + /** + * @brief Empthy constructor + * + */ layer_dense(); - // Contructor with layer size + /** + * @brief Constructor with input size and amount of neurons + * + * @param input_size Input size of data to the network. + * @param neurons Amount of neurons in the layer + * + */ layer_dense(panic::types::uint_t input_size, panic::types::uint_t neurons); - // Decontructor (All internal variables has decontructors, so we can just use default) + /** + * @brief Default de-constructor + * + */ ~layer_dense() = default; - // Forward function for forward pass + /** + * @brief Forward function for layer + * + * @param inputs Data input for forward pass. + * + * @Note Calculates -> outputs = inputs * weights + biases + */ bool forward(const panic::tensor::real_matrix& inputs); - // Backward pass + /** + * @brief Backward function for layer + * + * @param inputs Data input for bacward pass. + * + * @Note Calculates derivative of forward function. + */ bool backward(const panic::tensor::real_matrix& dinpus); }; diff --git a/include/neural_network/model/model.hpp b/include/neural_network/model/model.hpp new file mode 100644 index 0000000..0ed4ebb --- /dev/null +++ b/include/neural_network/model/model.hpp @@ -0,0 +1,178 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: neural_network + * File Name: model.hpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Defines the base model struct used in in neural network + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ +#pragma once + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//--------------------------------------------------------------------------------------------------------------------------- +#include // panic::types::uint_t, int_t and real_t +#include // panic::tensor::real_matrix + +#include // Base layer struct +#include // fully connected dense layer + +//--------------------------------------------------------------------------------------------------------------------------- +// TYPE DESCRIPTION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic{ + namespace neural_network{ + +/** + * @brief Basic neural network model. + * + * The model owns an array of layer pointers + * + * @note + * layer_count stores how many layers the model currently has. + * + * layers is a "pointer to pointers" -> layer** layers; + * That means it points to an array where each element is a layer* + * + * The struct is used for PANIC neural_network library. + */ +struct model{ + + /** + * @brief a pointer to a pointer of layers + * + * An example: + * layers[0] points to a layer_dense + * layers[1] points to an actication function + * layers[2] points to another layer_dense + * + * @note The model owns these layers and deletes them in clear(). + * + */ + layer** layers; + + // Number of layers currently stored in the model. + /** + * @brief Stores the number of layers + * + */ + panic::types::uint_t layer_count; + + // model output (may be deleted and also used for debug) + panic::tensor::real_matrix outputs; + + /** + * @brief Empthy constructor + * + */ + model(); + + /** + * @brief De-constructor + * + * @note Calls clear() to delete all layers and releases the layer pointer array + * + */ + ~model(); + + // Add an already-created layer to the model. + // Helper function for e.g. model.add_dense(5,5) + + /** + * @brief Helper function for adding layers + * + * Computes: + * @code + * layer_dense* new_layer = new layer_dense(3, 4); + * add(new_layer) + * @endcode + * + * @note it adds an already-inplemented layer to the model. + * + */ + bool add(layer* new_layer); + + // Create and add a dense layer. + + /** + * @brief Adds a dense layer to the model. + * + * Computes: + * @code + * model.add_layer_dense(3,4); + * @endcode + * + * @param inputs_size Input size of the data. + * @param neuron_count Number of neurons in the layer. + * + * @return true if layer is added + * + * @note This function is convenient, but it allocates a new layer. + */ + bool add_layer_dense( + panic::types::uint_t input_size, + panic::types::uint_t neuron_count + ); + + /** + * @brief Loops over all layers forward function + * + * Computes: + * @code + * model.forward(input_data_matrix) + * @endcode + * + * @param inputs Input data. + * + * @return true looped over every layer. + * + * @note It takes the privious layer outputs and uses it as + * the next layers input in the forward function. + * + */ + bool forward(const panic::tensor::real_matrix& inputs); + + // Delete all layers and reset the model. + + /** + * @brief Clears and deletes all layers and resets the model + * + * Computes: + * @code + * model.clear(); + * @endcode + * + * @note Primary used in the de-construtor. + * + */ + void clear(); +}; + + } // namespace neural_network +} // namespace panic \ No newline at end of file diff --git a/include/random/seed.hpp b/include/random/seed.hpp index 6b77268..1849fbf 100644 --- a/include/random/seed.hpp +++ b/include/random/seed.hpp @@ -38,12 +38,6 @@ #include // panic::uint_t, panic::int_t, and panic::real_t -//-------------------------------------------------------------------------------------------------------------------------- -// Function Name : panic::random::seed -// -// Description: -// base for random libary -//-------------------------------------------------------------------------------------------------------------------------- namespace panic{ namespace random{ @@ -77,8 +71,6 @@ struct seed_t{ */ bool set(panic::types::uint_t seed); - // Creates a deterministic state from the seed and an index. - // This is OMP-friendly because it does not modify shared memory. /** * @brief Returns a random number based on seed and index * diff --git a/main.cpp b/main.cpp index 71c36a6..928f3b1 100644 --- a/main.cpp +++ b/main.cpp @@ -45,6 +45,8 @@ #include #include #include +#include +#include @@ -756,6 +758,25 @@ int main(void) { panic::random::uniform(D3, 100.f, 200.f); panic::io::print_matrix(D3); + std::cout << "neural_network" << std::endl; + + panic::neural_network::layer_dense layer_dense01(3,4); + std::cout << layer_dense01.forward(D1) << std::endl; + panic::io::print_matrix(layer_dense01.outputs); + + + + + panic::neural_network::model mymodel; + + mymodel.add_layer_dense(3,4); + mymodel.forward(D1); + + + + + + return 0; diff --git a/src/math/add.cpp b/src/math/add.cpp index ec49721..df9b4a1 100644 --- a/src/math/add.cpp +++ b/src/math/add.cpp @@ -51,8 +51,7 @@ * Small vectors and matrices are kept serial because the overhead of starting * worker threads can be larger than the work itself. */ -//static const panic::types::uint_t add_omp_min_work = 10000; -static const panic::types::uint_t add_omp_min_work = 0; +static const panic::types::uint_t add_omp_min_work = 500; //--------------------------------------------------------------------------------------------------------------------------- // INPLEMENTATION //--------------------------------------------------------------------------------------------------------------------------- diff --git a/src/math/mul.hpp b/src/math/mul.hpp new file mode 100644 index 0000000..e69de29 diff --git a/src/neural_network/layer/layer_dense.cpp b/src/neural_network/layer/layer_dense.cpp index 9534b71..cde95fc 100644 --- a/src/neural_network/layer/layer_dense.cpp +++ b/src/neural_network/layer/layer_dense.cpp @@ -24,7 +24,7 @@ * Module Name: neural_network * File Name: layer_dense.cpp * Revision: 0.1.0 - * Date: 23-06-2026 + * Date: 28-07-2026 * Author: Michelle Bausager * * Description: @@ -37,25 +37,25 @@ //--------------------------------------------------------------------------------------------------------------------------- #include #include + #include #include +#include //--------------------------------------------------------------------------------------------------------------------------- -// DEFINE DESCRIPTION +// PRIVATE CONSTANTS +//--------------------------------------------------------------------------------------------------------------------------- +/** + * @brief Minimum number of element operations before using the OpenMP-enabled loop. + * + * Small vectors and matrices are kept serial because the overhead of starting + * worker threads can be larger than the work itself. + */ +static const panic::types::uint_t layer_dense_omp_min_size = 500; +//--------------------------------------------------------------------------------------------------------------------------- +// INPLEMENTATION //--------------------------------------------------------------------------------------------------------------------------- -//--------------------------------------------------------------------------------------------------------------------------- -// TYPE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- - -//--------------------------------------------------------------------------------------------------------------------------- -// VARIABLE DESCRIPTION -//--------------------------------------------------------------------------------------------------------------------------- -static const panic::types::uint_t layer_dense_omp_min_size = 10000; - -//--------------------------------------------------------------------------------------------------------------------------- -// FUNCTION PROTOTYPE -//--------------------------------------------------------------------------------------------------------------------------- namespace panic{ namespace neural_network{ @@ -76,27 +76,19 @@ layer_dense::layer_dense() { // Constructor Name : panic::neural_network::layer_dense // // Description: -// Creates an empty layer. +// Creates an empty layer with neurons. //-------------------------------------------------------------------------------------------------------------------------- layer_dense::layer_dense(panic::types::uint_t input_size, panic::types::uint_t neurons) { weights.resize(input_size, neurons); + panic::random::uniform(weights); + //panic::math::matmul(weights, 0.01f); + biases.resize(neurons); + panic::random::uniform(biases); + outputs.resize(0,0); } -//-------------------------------------------------------------------------------------------------------------------------- -// Deconstructor Name : panic::tensor::vector::~vector -// -// Description: -// Deletes the data and releases the memory. -//-------------------------------------------------------------------------------------------------------------------------- -//template -//vector::~vector(){ -// delete[] data; -// -// data = 0; -// length = 0; -//} //-------------------------------------------------------------------------------------------------------------------------- // Function Name : panic::neural_network::layer_dense.forward diff --git a/src/neural_network/model/model.cpp b/src/neural_network/model/model.cpp new file mode 100644 index 0000000..147b10c --- /dev/null +++ b/src/neural_network/model/model.cpp @@ -0,0 +1,234 @@ +/**++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * PANIC + * Portable Algorithms and Numerics In C++ + * + * Scientific computing from scratch, with feeling. + * + * Copyright (c) 2026 Michelle Bausager + * + * This file is part of PANIC. + * + * PANIC is free software licensed under the GNU General Public License v3.0 or later. + * You may redistribute and/or modify it under the terms of the GPL. + * + * PANIC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the LICENSE file for the full license text. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * + * Project Name: PANIC + * Module Name: neural_network + * File Name: model.cpp + * Revision: 0.1.0 + * Date: 25-06-2026 + * Author: Michelle Bausager + * + * Description: + * Defines the base model struct used in in neural network + * + *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ + +//--------------------------------------------------------------------------------------------------------------------------- +// INCLUDE DESCRIPTION +//--------------------------------------------------------------------------------------------------------------------------- +#include +#include +#include +#include + +//--------------------------------------------------------------------------------------------------------------------------- +// IMPLEMENTATION +//--------------------------------------------------------------------------------------------------------------------------- + +namespace panic{ + namespace neural_network{ + +//-------------------------------------------------------------------------------------------------------------------------- +// Constructor Name : panic::neural_network::model +// +// Description: +// Creates an empty model. +//-------------------------------------------------------------------------------------------------------------------------- +model::model(){ + + // No layers yet. + layers = 0; + + // Number of layers is zero. + layer_count = 0; + +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Destructor Name : panic::neural_network::model::~model +// +// Description: +// Deletes all layers owned by the model. +//-------------------------------------------------------------------------------------------------------------------------- +model::~model(){ + clear(); +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::model::add +// +// Description: +// Adds a layer to the model. +// +// The layer pointer array +// is resized every time a new layer is added. +//-------------------------------------------------------------------------------------------------------------------------- +bool model::add(layer* new_layer){ + + // Do not add a null layer. + if (new_layer == 0){ + return false; + } + + // The new array needs room for all old layers plus the new one. + const panic::types::uint_t new_layer_count = layer_count + 1; + + // Allocate a new array of layer pointers. + // + // layer* means "pointer to one layer" + // layer** means "pointer to many layer pointers" + // + // So this creates: + // + // [ layer* ][ layer* ][ layer* ] ... + // + layer** new_layers = new layer*[new_layer_count]; + + // Copy the old layer pointers into the new array. + // + // Important: + // This does not copy the layers themselves. + // It only copies the addresses of the layers. + for (panic::types::uint_t i = 0; i < layer_count; ++i){ + new_layers[i] = layers[i]; + } + + // Put the new layer at the end. + new_layers[layer_count] = new_layer; + + // Delete the old array of pointers. + // + // Important: + // Do NOT delete layers[i] here. + // The actual layer objects are still used in new_layers. + // + // This only deletes the old pointer array. + delete[] layers; + + // Make the model use the new bigger array. + layers = new_layers; + + // Update the layer count. + layer_count = new_layer_count; + + return true; +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::model::add_layer_dense +// +// Description: +// Creates a dense layer and adds it to the model. +// +// Example: +// model.add_dense(100, 64); +//-------------------------------------------------------------------------------------------------------------------------- +bool model::add_layer_dense( + panic::types::uint_t input_size, + panic::types::uint_t neuron_count){ + + // Create the dense layer. + layer_dense* new_layer = new layer_dense(input_size, neuron_count); + + if (new_layer == 0){ + return false; + } + + // Add it to the model. + // + // If add() fails, delete the layer so we do not leak memory. + if (!add(new_layer)){ + delete new_layer; + return false; + } + + return true; +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::model::forward +// +// Description: +// Runs the input through every layer in order. +//-------------------------------------------------------------------------------------------------------------------------- +bool model::forward(const panic::tensor::real_matrix& inputs){ + + // If the model has no layers, just copy inputs to outputs. + if (layer_count == 0){ + outputs = inputs; + return true; + } + + // First layer receives the original model input. + if (!layers[0]->forward(inputs)){ + return false; + } + + // Every next layer receives the output from the previous layer. + // If it fails, return false + for (panic::types::uint_t i = 1; i < layer_count; ++i){ + + if (!layers[i]->forward(layers[i - 1] -> outputs)){ + return false; + } + } + + // The model output is the output of the last layer. + outputs = layers[layer_count - 1] -> outputs; + + return true; +} + + +//-------------------------------------------------------------------------------------------------------------------------- +// Function Name : panic::neural_network::model::clear +// +// Description: +// Deletes all layers and resets the model. +//-------------------------------------------------------------------------------------------------------------------------- +void model::clear(){ + + if (layers != 0){ + + // Delete each actual layer object. + for (panic::types::uint_t i = 0; i < layer_count; ++i){ + delete layers[i]; + layers[i] = 0; + } + + // Delete the array that stored the layer pointers. + delete[] layers; + } + + // Reset to empty state. + layers = 0; + layer_count = 0; + + outputs.resize(0, 0); +} + + } // namespace neural_network +} // namespace panic \ No newline at end of file