LCOV - code coverage report
Current view: top level - include - Layer.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 20 21 95.2 %
Date: 2024-12-28 17:36:05 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /**
       2             :  * @file Layer.h
       3             :  * @author Damien Balima (www.dams-labs.net)
       4             :  * @brief Abstract layer class
       5             :  * @date 2023-08-27
       6             :  *
       7             :  * @copyright Damien Balima (c) CC-BY-NC-SA-4.0 2023
       8             :  *
       9             :  */
      10             : #pragma once
      11             : #include "ActivationFunctions.h"
      12             : #include "Neuron.h"
      13             : #include "exception/NeuralNetworkException.h"
      14             : #include <atomic>
      15             : #include <cstddef>
      16             : #include <execution>
      17             : #include <functional>
      18             : #include <map>
      19             : #include <opencv2/opencv.hpp>
      20             : #include <thread>
      21             : 
      22             : namespace sipai {
      23             : class VulkanController;
      24             : 
      25             : using NeuronMat = std::vector<std::vector<Neuron>>;
      26             : 
      27             : enum class LayerType { LayerInput, LayerHidden, LayerOutput };
      28             : 
      29             : const std::map<std::string, LayerType, std::less<>> layer_map{
      30             :     {"LayerInput", LayerType::LayerInput},
      31             :     {"LayerHidden", LayerType::LayerHidden},
      32             :     {"LayerOutput", LayerType::LayerOutput}};
      33             : 
      34             : /**
      35             :  * @brief The Layer class represents a layer in a neural network. It contains a
      36             :  * vector of Neurons and has methods for forward propagation, backward
      37             :  * propagation, and updating weights.
      38             :  */
      39             : class Layer {
      40             : public:
      41          28 :   explicit Layer(LayerType layerType, size_t size_x = 0, size_t size_y = 0)
      42          28 :       : layerType(layerType), size_x(size_x), size_y(size_y) {
      43          28 :     neurons = NeuronMat(size_y, std::vector<Neuron>(size_x));
      44          90 :     for (size_t y = 0; y < size_y; ++y) {
      45         232 :       for (size_t x = 0; x < size_x; ++x) {
      46         170 :         neurons[y][x].index_x = x;
      47         170 :         neurons[y][x].index_y = y;
      48             :       }
      49             :     }
      50          28 :     values = cv::Mat((int)size_y, (int)size_x, CV_32FC4);
      51          28 :     errors = cv::Mat((int)size_y, (int)size_x, CV_32FC4);
      52          28 :   }
      53          28 :   virtual ~Layer() = default;
      54             : 
      55             :   const LayerType layerType;
      56             : 
      57             :   /**
      58             :    * @brief 2D vector of neurons in format [rows][cols], i.e. [y][x]
      59             :    *
      60             :    */
      61             :   NeuronMat neurons;
      62             : 
      63             :   /**
      64             :    * @brief 2D matrix of values, in format (x,y)
      65             :    *
      66             :    */
      67             :   cv::Mat values;
      68             : 
      69             :   /**
      70             :    * @brief 2D matrix of errors, in format (x,y)
      71             :    *
      72             :    */
      73             :   cv::Mat errors;
      74             : 
      75             :   /**
      76             :    * @brief previous layer, or nullptr if not exists
      77             :    *
      78             :    */
      79             :   Layer *previousLayer = nullptr;
      80             : 
      81             :   /**
      82             :    * @brief next layer, or nullptr if not exists
      83             :    *
      84             :    */
      85             :   Layer *nextLayer = nullptr;
      86             : 
      87             :   /**
      88             :    * @brief width (columns)
      89             :    *
      90             :    */
      91             :   size_t size_x = 0;
      92             : 
      93             :   /**
      94             :    * @brief height (rows)
      95             :    *
      96             :    */
      97             :   size_t size_y = 0;
      98             : 
      99             :   /**
     100             :    * @brief Get the layer total size, which is (size_x * size_y)
     101             :    *
     102             :    * @return size_t
     103             :    */
     104         232 :   size_t total() const { return size_x * size_y; }
     105             : 
     106             :   /**
     107             :    * @brief Get the indexes (x,y) of a neuron from the layer size() index
     108             :    *
     109             :    * @param index
     110             :    * @return std::pair<size_t, size_t>
     111             :    */
     112             :   std::pair<size_t, size_t> getPos(const size_t &index) const {
     113             :     if (index >= total()) {
     114             :       throw std::out_of_range("Index out of range");
     115             :     }
     116             :     size_t row = index / size_x;
     117             :     size_t col = index % size_x;
     118             :     return {row, col};
     119             :   }
     120             : 
     121             :   /**
     122             :    * @brief Get a neuron from a layer size() index
     123             :    *
     124             :    * @param index
     125             :    * @return Neuron&
     126             :    */
     127             :   Neuron &getNeuron(const size_t &index) {
     128             :     const auto &[row, col] = getPos(index);
     129             :     return neurons[row][col];
     130             :   }
     131             : 
     132             :   EActivationFunction eactivationFunction = EActivationFunction::ReLU;
     133             :   float activationFunctionAlpha = 0.0f;
     134             :   std::function<cv::Vec4f(cv::Vec4f)> activationFunction;
     135             :   std::function<cv::Vec4f(cv::Vec4f)> activationFunctionDerivative;
     136             : 
     137             :   const std::string UndefinedLayer = "UndefinedLayer";
     138             : 
     139             :   /**
     140             :    * @brief Apply a function on all the layer neurons
     141             :    *
     142             :    * @tparam Function a lambda function
     143             :    * @param operation
     144             :    */
     145             :   template <typename Function> void apply(Function operation) {
     146             :     for (auto &neuronRow : neurons) {
     147             :       for (auto &neuron : neuronRow) {
     148             :         operation(neuron);
     149             :       }
     150             :     }
     151             :   }
     152             : 
     153             :   /**
     154             :    * @brief Performs forward propagation using the previous layer.
     155             :    */
     156             :   virtual void forwardPropagation();
     157             : 
     158             :   /**
     159             :    * @brief Performs backward propagation using the next layer.
     160             :    */
     161             :   virtual void backwardPropagation(const float &error_min,
     162             :                                    const float &error_max);
     163             :   /**
     164             :    * @brief Updates the weights of the neurons in this layer using the
     165             :    * previous layer and a learning rate.
     166             :    *
     167             :    * @param learningRate The learning rate to use when updating weights.
     168             :    */
     169             :   virtual void updateWeights(float learningRate);
     170             : 
     171          12 :   const std::string getLayerTypeStr() const {
     172          24 :     for (const auto &[key, mLayerType] : layer_map) {
     173          24 :       if (mLayerType == layerType) {
     174          12 :         return key;
     175             :       }
     176             :     }
     177           0 :     return UndefinedLayer;
     178             :   }
     179             : 
     180             :   void
     181          25 :   setActivationFunction(const std::function<cv::Vec4f(cv::Vec4f)> &function,
     182             :                         const std::function<cv::Vec4f(cv::Vec4f)> &derivative) {
     183          25 :     activationFunction = function;
     184          25 :     activationFunctionDerivative = derivative;
     185          25 :   }
     186             : };
     187             : } // namespace sipai

Generated by: LCOV version 1.16