LCOV - code coverage report
Current view: top level - ml - Conv.cpp (source / functions) Hit Total Coverage
Test: test_coverage.info.cleaned Lines: 53 87 60.9 %
Date: 2022-07-06 02:47:47 Functions: 10 16 62.5 %

          Line data    Source code
       1             : #include "Conv.h"
       2             : #include "TypeCasts.hpp"
       3             : 
       4             : namespace elsa::ml
       5             : {
       6             :     template <typename data_t>
       7           2 :     ConvBase<data_t>::ConvBase(LayerType layerType, index_t numberOfFilters,
       8             :                                const VolumeDescriptor& filterDescriptor, Activation activation,
       9             :                                index_t strides, Padding padding, bool useBias,
      10             :                                Initializer kernelInitializer, Initializer biasInitializer,
      11             :                                const std::string& name, int requiredNumberOfDimensions)
      12             :         : Trainable<data_t>(layerType, activation, useBias, kernelInitializer, biasInitializer,
      13             :                             name, requiredNumberOfDimensions),
      14             :           numberOfFilters_(numberOfFilters),
      15             :           filterDescriptor_(filterDescriptor.clone()),
      16             :           strides_(strides),
      17           2 :           padding_(padding)
      18             :     {
      19           2 :     }
      20             : 
      21             :     template <typename data_t>
      22           3 :     index_t ConvBase<data_t>::getNumberOfFilters() const
      23             :     {
      24           3 :         return numberOfFilters_;
      25             :     }
      26             : 
      27             :     template <typename data_t>
      28           4 :     VolumeDescriptor ConvBase<data_t>::getFilterDescriptor() const
      29             :     {
      30           4 :         if (!filterDescriptor_)
      31           0 :             throw std::logic_error("Filter descriptor not set");
      32             : 
      33             :         // Downcast to VolumeDescriptor
      34           4 :         return downcast<VolumeDescriptor>(*filterDescriptor_);
      35             :     }
      36             : 
      37             :     template <typename data_t>
      38           3 :     index_t ConvBase<data_t>::getStrides() const
      39             :     {
      40           3 :         return strides_;
      41             :     }
      42             : 
      43             :     template <typename data_t>
      44           1 :     Padding ConvBase<data_t>::getPadding() const
      45             :     {
      46           1 :         return padding_;
      47             :     }
      48             : 
      49             :     template <typename data_t>
      50           2 :     Conv<data_t>::Conv(index_t convolutionDimensions, index_t numberOfFilters,
      51             :                        const VolumeDescriptor& filterDescriptor, Activation activation,
      52             :                        index_t strides, Padding padding, bool useBias,
      53             :                        Initializer kernelInitializer, Initializer biasInitializer,
      54             :                        const std::string& name)
      55             :         : ConvBase<data_t>(
      56             :             convolutionDimensions == 1
      57             :                 ? LayerType::Conv1D
      58             :                 : (convolutionDimensions == 2 ? LayerType::Conv2D : LayerType::Conv3D),
      59             :             numberOfFilters, filterDescriptor, activation, strides, padding, useBias,
      60             :             kernelInitializer, biasInitializer, name,
      61             :             /* required number of input dims */ static_cast<int>(convolutionDimensions) + 1),
      62           2 :           convolutionDimensions_(convolutionDimensions)
      63             :     {
      64           2 :     }
      65             : 
      66             :     template <typename data_t>
      67           1 :     IndexVector_t Conv<data_t>::getPaddingSizes() const
      68             :     {
      69             :         // We pad spatial dimensions only
      70           1 :         IndexVector_t paddingSize(asUnsigned(this->convolutionDimensions_));
      71             : 
      72           1 :         switch (this->getPadding()) {
      73             :             // Valid padding means no padding at all
      74           0 :             case Padding::Valid:
      75           0 :                 paddingSize.setZero();
      76           0 :                 break;
      77             :             // Same padding means we pad the input such that the output has unchanges spatial
      78             :             // dimensions. In theory we wouldn't need to do anything here since we already
      79             :             // know the dimensions of the output descriptor (same as the ones of the input
      80             :             // descriptor), however, the backend won't understand magic terms such as *Valid* or
      81             :             // *Same* and needs bare padding numbers.
      82             :             //
      83             :             // Since the spatial output dimensions of a convolution operations
      84             :             // calculates as
      85             :             //    o = (i-p+k)/s+1
      86             :             // we calculate same padding as
      87             :             //  p = s(i-1)-1-k
      88           1 :             case Padding::Same:
      89           3 :                 for (int dim = 0; dim < paddingSize.size(); ++dim) {
      90           2 :                     const index_t inputDim =
      91           2 :                         this->getInputDescriptor().getNumberOfCoefficientsPerDimension()[dim];
      92           2 :                     const index_t kernelDim =
      93           2 :                         this->getFilterDescriptor().getNumberOfCoefficientsPerDimension()[dim];
      94           2 :                     paddingSize[dim] = this->getStrides() * (inputDim - 1) - inputDim + kernelDim;
      95             :                 }
      96           1 :                 break;
      97             :         }
      98           1 :         return paddingSize;
      99             :     }
     100             : 
     101             :     template <typename data_t>
     102           1 :     void Conv<data_t>::computeOutputDescriptor()
     103             :     {
     104           1 :         if (this->inputDescriptors_.size() != 1) {
     105             :             throw std::invalid_argument(
     106           0 :                 "Cannot compute output descriptor without input descriptor");
     107             :         }
     108             : 
     109           2 :         if (this->inputDescriptors_.front()->getNumberOfCoefficientsPerDimension().tail(1)(0)
     110           1 :             != this->filterDescriptor_->getNumberOfCoefficientsPerDimension().tail(1)(0))
     111           0 :             throw std::invalid_argument("Input and filter channels must match");
     112             : 
     113           2 :         IndexVector_t dims(convolutionDimensions_ + 1);
     114           2 :         auto padding = getPaddingSizes();
     115           3 :         for (index_t idx = 0; idx < convolutionDimensions_; ++idx) {
     116             :             // output = (input - kernel + 2 * padding) / stride + 1
     117           4 :             dims[idx] = (this->inputDescriptors_.front()->getNumberOfCoefficientsPerDimension()[idx]
     118           4 :                          - this->filterDescriptor_->getNumberOfCoefficientsPerDimension()[idx]
     119           2 :                          + padding[idx])
     120           2 :                             / this->strides_
     121           2 :                         + 1;
     122             :         }
     123           1 :         dims(convolutionDimensions_) = this->numberOfFilters_;
     124           1 :         VolumeDescriptor desc(dims);
     125           1 :         this->outputDescriptor_ = desc.clone();
     126           1 :         this->numberOfTrainableParameters_ =
     127           2 :             this->getNumberOfFilters() * this->getFilterDescriptor().getNumberOfCoefficients()
     128           1 :             + (this->useBias_ ? this->getNumberOfFilters() : 0);
     129           1 :     }
     130             : 
     131             :     template <typename data_t>
     132           1 :     Conv1D<data_t>::Conv1D(index_t numberOfFilters, const VolumeDescriptor& filterDescriptor,
     133             :                            Activation activation, index_t strides, Padding padding, bool useBias,
     134             :                            Initializer kernelInitializer, Initializer biasInitializer,
     135             :                            const std::string& name)
     136             :         : Conv<data_t>(1, numberOfFilters, filterDescriptor, activation, strides, padding, useBias,
     137           1 :                        kernelInitializer, biasInitializer, name)
     138             :     {
     139           1 :     }
     140             : 
     141             :     template <typename data_t>
     142           0 :     Conv1D<data_t>::Conv1D(index_t numberOfFilters, const std::array<index_t, 2>& filterSize,
     143             :                            Activation activation, index_t strides, Padding padding, bool useBias,
     144             :                            Initializer kernelInitializer, Initializer biasInitializer,
     145             :                            const std::string& name)
     146             :         : Conv<data_t>(1, numberOfFilters,
     147           0 :                        VolumeDescriptor(IndexVector_t{
     148             :                            {/* width */ filterSize[0], /* channels */ filterSize[1]}}),
     149             :                        activation, strides, padding, useBias, kernelInitializer, biasInitializer,
     150           0 :                        name)
     151             :     {
     152           0 :     }
     153             : 
     154             :     template <typename data_t>
     155           0 :     Conv2D<data_t>::Conv2D(index_t numberOfFilters, const VolumeDescriptor& filterDescriptor,
     156             :                            Activation activation, index_t strides, Padding padding, bool useBias,
     157             :                            Initializer kernelInitializer, Initializer biasInitializer,
     158             :                            const std::string& name)
     159             :         : Conv<data_t>(2, numberOfFilters, filterDescriptor, activation, strides, padding, useBias,
     160           0 :                        kernelInitializer, biasInitializer, name)
     161             :     {
     162           0 :     }
     163             : 
     164             :     template <typename data_t>
     165           1 :     Conv2D<data_t>::Conv2D(index_t numberOfFilters, const std::array<index_t, 3>& filterSize,
     166             :                            Activation activation, index_t strides, Padding padding, bool useBias,
     167             :                            Initializer kernelInitializer, Initializer biasInitializer,
     168             :                            const std::string& name)
     169             :         : Conv<data_t>(
     170             :             2, numberOfFilters,
     171           3 :             VolumeDescriptor(IndexVector_t{{/* width */ filterSize[0], /* height */ filterSize[1],
     172             :                                             /* channels */ filterSize[2]}}),
     173           1 :             activation, strides, padding, useBias, kernelInitializer, biasInitializer, name)
     174             :     {
     175           1 :     }
     176             : 
     177             :     template <typename data_t>
     178           0 :     Conv3D<data_t>::Conv3D(index_t numberOfFilters, const VolumeDescriptor& filterDescriptor,
     179             :                            Activation activation, index_t strides, Padding padding, bool useBias,
     180             :                            Initializer kernelInitializer, Initializer biasInitializer,
     181             :                            const std::string& name)
     182             :         : Conv<data_t>(3, numberOfFilters, filterDescriptor, activation, strides, padding, useBias,
     183           0 :                        kernelInitializer, biasInitializer, name)
     184             :     {
     185           0 :     }
     186             : 
     187             :     template <typename data_t>
     188           0 :     ConvTranspose<data_t>::ConvTranspose(index_t convolutionDimensions, index_t numberOfFilters,
     189             :                                          const VolumeDescriptor& filterDescriptor,
     190             :                                          Activation activation, index_t strides, Padding padding,
     191             :                                          bool useBias, Initializer kernelInitializer,
     192             :                                          Initializer biasInitializer, const std::string& name)
     193             :         : ConvBase<data_t>(
     194             :             convolutionDimensions == 2 ? LayerType::Conv2DTranspose : LayerType::Conv3DTranspose,
     195             :             numberOfFilters, filterDescriptor, activation, strides, padding, useBias,
     196             :             kernelInitializer, biasInitializer, name,
     197             :             /* required number of input dims */ static_cast<int>(convolutionDimensions) + 1),
     198           0 :           convolutionDimensions_(convolutionDimensions)
     199             :     {
     200           0 :     }
     201             : 
     202             :     template <typename data_t>
     203           0 :     void ConvTranspose<data_t>::computeOutputDescriptor()
     204             :     {
     205             :         // Spatial dimension + channels
     206           0 :         IndexVector_t dims(convolutionDimensions_ + 1);
     207             : 
     208             :         // using (width x height x channels) we get
     209             : 
     210             :         // TODO(tellenbach): Add padding
     211           0 :         for (index_t idx = 0; idx < convolutionDimensions_; ++idx) {
     212           0 :             dims[idx] =
     213           0 :                 this->strides_
     214           0 :                     * (this->inputDescriptors_.front()->getNumberOfCoefficientsPerDimension()[idx]
     215           0 :                        - 1)
     216           0 :                 + this->filterDescriptor_
     217           0 :                       ->getNumberOfCoefficientsPerDimension()[idx]; //- 2 * padding[idx];
     218             :         }
     219           0 :         dims(convolutionDimensions_) = this->numberOfFilters_;
     220             : 
     221           0 :         this->outputDescriptor_ = VolumeDescriptor(dims).clone();
     222           0 :     }
     223             : 
     224             :     template <typename data_t>
     225           0 :     Conv2DTranspose<data_t>::Conv2DTranspose(index_t numberOfFilters,
     226             :                                              const VolumeDescriptor& filterDescriptor,
     227             :                                              Activation activation, index_t strides,
     228             :                                              Padding padding, bool useBias,
     229             :                                              Initializer kernelInitializer,
     230             :                                              Initializer biasInitializer, const std::string& name)
     231             :         : ConvTranspose<data_t>(2, numberOfFilters, filterDescriptor, activation, strides, padding,
     232           0 :                                 useBias, kernelInitializer, biasInitializer, name)
     233             :     {
     234           0 :     }
     235             : 
     236             :     template class ConvBase<float>;
     237             :     template class Conv<float>;
     238             :     template struct Conv1D<float>;
     239             :     template struct Conv2D<float>;
     240             :     template struct Conv3D<float>;
     241             :     template class ConvTranspose<float>;
     242             :     template struct Conv2DTranspose<float>;
     243             : 
     244             : } // namespace elsa::ml

Generated by: LCOV version 1.15