Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:53

0001 // @(#)root/tmva/tmva/dnn:$Id$
0002 // Author: Vladimir Ilievski
0003 
0004 /**********************************************************************************
0005  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
0006  * Package: TMVA                                                                  *
0007  * Class  : TConvLayer                                                            *
0008  *                                             *
0009  *                                                                                *
0010  * Description:                                                                   *
0011  *      Convolutional Deep Neural Network Layer                                   *
0012  *                                                                                *
0013  * Authors (alphabetical):                                                        *
0014  *      Vladimir Ilievski      <ilievski.vladimir@live.com>  - CERN, Switzerland  *
0015  *                                                                                *
0016  * Copyright (c) 2005-2015:                                                       *
0017  *      CERN, Switzerland                                                         *
0018  *      U. of Victoria, Canada                                                    *
0019  *      MPI-K Heidelberg, Germany                                                 *
0020  *      U. of Bonn, Germany                                                       *
0021  *                                                                                *
0022  * Redistribution and use in source and binary forms, with or without             *
0023  * modification, are permitted according to the terms listed in LICENSE           *
0024  * (see tmva/doc/LICENSE)                                          *
0025  **********************************************************************************/
0026 
0027 #ifndef TMVA_CNN_CONVLAYER
0028 #define TMVA_CNN_CONVLAYER
0029 
0030 #include "TMatrix.h"
0031 
0032 #include "TMVA/DNN/GeneralLayer.h"
0033 #include "TMVA/DNN/Functions.h"
0034 #include "TMVA/DNN/CNN/ContextHandles.h"
0035 
0036 #include <vector>
0037 #include <iostream>
0038 #include <string>
0039 
0040 namespace TMVA {
0041 namespace DNN {
0042 namespace CNN {
0043 
0044 typedef struct TConvParams {
0045 
0046 public:
0047    size_t batchSize; ///< Batch size used for training and evaluation
0048 
0049    size_t inputDepth;  ///< The depth of the previous layer or input.
0050    size_t inputHeight; ///< The height of the previous layer or input.
0051    size_t inputWidth;  ///< The width of the previous layer or input.
0052 
0053    size_t numberFilters; ///< The number of the filters, which is equal to the output's depth.
0054    size_t filterHeight;  ///< The height of the filter.
0055    size_t filterWidth;   ///< The width of the filter.
0056 
0057    size_t strideRows;    ///< The number of row pixels to slid the filter each step.
0058    size_t strideCols;    ///< The number of column pixels to slid the filter each step.
0059    size_t paddingHeight; ///< The number of zero layers added top and bottom of the input.
0060    size_t paddingWidth;  ///< The number of zero layers left and right of the input.
0061 
0062    TConvParams(size_t _batchSize, size_t _inputDepth, size_t _inputHeight, size_t _inputWidth, size_t _numberFilters,
0063                size_t _filterHeight, size_t _filterWidth, size_t _strideRows, size_t _strideCols,
0064                size_t _paddingHeight, size_t _paddingWidth)
0065            : batchSize(_batchSize), inputDepth(_inputDepth), inputHeight(_inputHeight), inputWidth(_inputWidth),
0066              numberFilters(_numberFilters), filterHeight(_filterHeight), filterWidth(_filterWidth),
0067              strideRows(_strideRows), strideCols(_strideCols), paddingHeight(_paddingHeight),
0068              paddingWidth(_paddingWidth)
0069    {}
0070 } TConvParams;
0071 
0072 
0073 
0074 template <typename Architecture_t>
0075 class TConvLayer : public VGeneralLayer<Architecture_t> {
0076 public:
0077    using Tensor_t = typename Architecture_t::Tensor_t;
0078    using Matrix_t = typename Architecture_t::Matrix_t;
0079    using Scalar_t = typename Architecture_t::Scalar_t;
0080 
0081    using LayerDescriptor_t   = typename Architecture_t::ConvolutionDescriptor_t;
0082    using WeightsDescriptor_t = typename Architecture_t::FilterDescriptor_t;
0083    using HelperDescriptor_t  = typename Architecture_t::ActivationDescriptor_t;
0084 
0085    using AlgorithmForward_t  = typename Architecture_t::AlgorithmForward_t;  // Forward layer operation
0086    using AlgorithmBackward_t = typename Architecture_t::AlgorithmBackward_t; // Backward layer operation
0087    using AlgorithmHelper_t   = typename Architecture_t::AlgorithmHelper_t;   // Used for weight grad backward pass
0088    using ReduceTensorDescriptor_t = typename Architecture_t::ReduceTensorDescriptor_t; // used for reduction of tensor(bias grad)
0089 
0090    // FIXME: Add other cudnn types (algorithm preference etc.)
0091    using AlgorithmDataType_t = typename Architecture_t::AlgorithmDataType_t;
0092 
0093    /* Calculate the output dimension of the convolutional layer */
0094    static size_t calculateDimension(size_t imgDim, size_t fltDim, size_t padding, size_t stride);
0095 
0096    /* Calculate the number of pixels in a single receptive field */
0097    static size_t inline calculateNLocalViewPixels(size_t depth, size_t height, size_t width) { return depth * height * width; }
0098 
0099    /* Calculate the number of receptive fields in an image given the filter and image sizes */
0100    static size_t calculateNLocalViews(size_t inputHeight, size_t filterHeight, size_t paddingHeight, size_t strideRows,
0101                                size_t inputWidth, size_t filterWidth, size_t paddingWidth, size_t strideCols);
0102 
0103 protected:
0104    size_t fFilterDepth;  ///< The depth of the filter.
0105    size_t fFilterHeight; ///< The height of the filter.
0106    size_t fFilterWidth;  ///< The width of the filter.
0107 
0108    size_t fStrideRows;   ///< The number of row pixels to slid the filter each step.
0109    size_t fStrideCols;   ///< The number of column pixels to slid the filter each step.
0110 
0111    size_t fNLocalViewPixels;     ///< The number of pixels in one local image view.
0112    size_t fNLocalViews;          ///< The number of local views in one image.
0113 
0114    Scalar_t fDropoutProbability; ///< Probability that an input is active.
0115 
0116    TDescriptors * fDescriptors = nullptr;  ///< Keeps the convolution, activations and filter descriptors
0117 
0118    TWorkspace * fWorkspace = nullptr;
0119 private:
0120    size_t fPaddingHeight;        ///< The number of zero layers added top and bottom of the input.
0121    size_t fPaddingWidth;         ///< The number of zero layers left and right of the input.
0122 
0123    Tensor_t fInputActivation;        ///< First output of this layer after conv, before activation.
0124 
0125    std::vector<int> fBackwardIndices;  ///< Vector of indices used for a fast Im2Col in backward pass
0126 
0127    EActivationFunction fF;             ///< Activation function of the layer.
0128    ERegularization fReg;               ///< The regularization method.
0129    Scalar_t fWeightDecay;              ///< The weight decay.
0130 
0131    Tensor_t fForwardTensor;            ///< Cache tensor used for speeding-up the forward pass.
0132 
0133    void InitializeDescriptors();
0134    void ReleaseDescriptors();
0135    void InitializeWorkspace();
0136    void FreeWorkspace();
0137 
0138 public:
0139    /*! Constructor. */
0140    TConvLayer(size_t BatchSize, size_t InputDepth, size_t InputHeight, size_t InputWidth, size_t Depth, EInitialization Init,
0141               size_t FilterHeight, size_t FilterWidth, size_t StrideRows, size_t StrideCols, size_t PaddingHeight,
0142               size_t PaddingWidth, Scalar_t DropoutProbability, EActivationFunction f, ERegularization Reg,
0143               Scalar_t WeightDecay);
0144 
0145    /*! Copy the conv layer provided as a pointer */
0146    TConvLayer(TConvLayer<Architecture_t> *layer);
0147 
0148    /*! Copy constructor. */
0149    TConvLayer(const TConvLayer &);
0150 
0151    /*! Destructor. */
0152    virtual ~TConvLayer();
0153 
0154    //virtual void Initialize();
0155 
0156    /*! Computes activation of the layer for the given input. The input
0157    * must be in 3D tensor form with the different matrices corresponding to
0158    * different events in the batch. Computes activations as well as
0159    * the first partial derivative of the activation function at those
0160    * activations. */
0161    void Forward(Tensor_t &input, bool applyDropout = false);
0162 
0163    /*! Compute weight, bias and activation gradients. Uses the precomputed
0164     *  first partial derivatives of the activation function computed during
0165     *  forward propagation and modifies them. Must only be called directly
0166     *  at the corresponding call to Forward(...). */
0167    void Backward(Tensor_t &gradients_backward, const Tensor_t &activations_backward);
0168    ////              Tensor_t &inp1, Tensor_t &inp2);
0169 
0170    /*! Prints the info about the layer. */
0171    void Print() const;
0172 
0173    /*! Writes the information and the weights about the layer in an XML node. */
0174    virtual void AddWeightsXMLTo(void *parent);
0175 
0176    /*! Read the information and the weights about the layer from XML node. */
0177    virtual void ReadWeightsFromXML(void *parent);
0178 
0179    /*! Getters */
0180    size_t GetFilterDepth() const { return fFilterDepth; }
0181    size_t GetFilterHeight() const { return fFilterHeight; }
0182    size_t GetFilterWidth() const { return fFilterWidth; }
0183 
0184    size_t GetStrideRows() const { return fStrideRows; }
0185    size_t GetStrideCols() const { return fStrideCols; }
0186 
0187    size_t GetPaddingHeight() const { return fPaddingHeight; }
0188    size_t GetPaddingWidth() const { return fPaddingWidth; }
0189 
0190    size_t GetNLocalViewPixels() const { return fNLocalViewPixels; }
0191    size_t GetNLocalViews() const { return fNLocalViews; }
0192 
0193    Scalar_t GetDropoutProbability() const { return fDropoutProbability; }
0194 
0195    const Tensor_t &GetInputActivation() const { return fInputActivation; }
0196    Tensor_t &GetInputActivation() { return fInputActivation; }
0197 
0198    Matrix_t &GetInputActivationAt(size_t i) { return fInputActivation[i]; }
0199    const Matrix_t &GetInputActivationAt(size_t i) const { return fInputActivation[i]; }
0200 
0201    const Tensor_t &GetForwardMatrices() const { return fForwardTensor; }
0202    Tensor_t &GetForwardMatrices() { return fForwardTensor; }
0203 
0204    EActivationFunction GetActivationFunction() const { return fF; }
0205    ERegularization GetRegularization() const { return fReg; }
0206    Scalar_t GetWeightDecay() const { return fWeightDecay; }
0207 
0208    // The following getters are used for testing
0209    TDescriptors * GetDescriptors() {return fDescriptors;}
0210    const TDescriptors * GetDescriptors() const {return fDescriptors;}
0211 
0212    TWorkspace * GetWorkspace() {return fWorkspace;}
0213    const TWorkspace * GetWorkspace() const {return fWorkspace;}
0214 };
0215 
0216 
0217 //
0218 //
0219 //  Conv Layer Class - Implementation
0220 //______________________________________________________________________________
0221 template <typename Architecture_t>
0222 TConvLayer<Architecture_t>::TConvLayer(size_t batchSize, size_t inputDepth, size_t inputHeight, size_t inputWidth,
0223                                        size_t depth, EInitialization init, size_t filterHeight, size_t filterWidth,
0224                                        size_t strideRows, size_t strideCols, size_t paddingHeight, size_t paddingWidth,
0225                                        Scalar_t dropoutProbability, EActivationFunction f, ERegularization reg,
0226                                        Scalar_t weightDecay)
0227    : VGeneralLayer<Architecture_t>(batchSize, inputDepth, inputHeight, inputWidth, depth,
0228                                    calculateDimension(inputHeight, filterHeight, paddingHeight, strideRows),
0229                                    calculateDimension(inputWidth, filterWidth, paddingWidth, strideCols),
0230                                    1, depth, calculateNLocalViewPixels(inputDepth, filterHeight, filterWidth),
0231                                    1, depth, 1, batchSize, depth,
0232                                    calculateNLocalViews(inputHeight, filterHeight, paddingHeight, strideRows,
0233                                                         inputWidth, filterWidth, paddingWidth, strideCols),
0234                                    init),
0235      fFilterDepth(inputDepth), fFilterHeight(filterHeight), fFilterWidth(filterWidth), fStrideRows(strideRows),
0236      fStrideCols(strideCols), fNLocalViewPixels(calculateNLocalViewPixels(inputDepth, filterHeight, filterWidth)),
0237      fNLocalViews(calculateNLocalViews(inputHeight, filterHeight, paddingHeight, strideRows,
0238                                        inputWidth, filterWidth, paddingWidth, strideCols)),
0239      fDropoutProbability(dropoutProbability), fPaddingHeight(paddingHeight), fPaddingWidth(paddingWidth),
0240      fInputActivation(), fF(f), fReg(reg), fWeightDecay(weightDecay)
0241 {
0242    /** Each element in the vector is a `T_Matrix` representing an event, therefore `vec.size() == batchSize`.
0243     *  Cells in these matrices are distributed in the following manner:
0244     *  Each row represents a single feature map, therefore we have `nRows == depth`.
0245     *  Each column represents a single pixel in that feature map, therefore we have `nCols == nLocalViews`.
0246     **/
0247    fInputActivation = Tensor_t( batchSize, depth, fNLocalViews);     // create tensor (shape is B x C x LV)
0248    fForwardTensor = Tensor_t ( batchSize, fNLocalViews, fNLocalViewPixels );
0249 
0250 
0251    InitializeDescriptors();
0252    InitializeWorkspace();
0253 }
0254 
0255 //______________________________________________________________________________
0256 template <typename Architecture_t>
0257 TConvLayer<Architecture_t>::TConvLayer(TConvLayer<Architecture_t> *layer)
0258    : VGeneralLayer<Architecture_t>(layer), fFilterDepth(layer->GetFilterDepth()),
0259      fFilterHeight(layer->GetFilterHeight()), fFilterWidth(layer->GetFilterWidth()),
0260      fStrideRows(layer->GetStrideRows()), fStrideCols(layer->GetStrideCols()),
0261      fNLocalViewPixels(layer->GetNLocalViewPixels()), fNLocalViews(layer->GetNLocalViews()),
0262      fDropoutProbability(layer->GetDropoutProbability()), fPaddingHeight(layer->GetPaddingHeight()),
0263      fPaddingWidth(layer->GetPaddingWidth()),
0264      fInputActivation( layer->GetInputActivation().GetShape() ),
0265      fF(layer->GetActivationFunction()),
0266      fReg(layer->GetRegularization()), fWeightDecay(layer->GetWeightDecay()),
0267      fForwardTensor( layer->GetForwardMatrices().GetShape() )
0268 {
0269    InitializeDescriptors();
0270    InitializeWorkspace();
0271 
0272 }
0273 
0274 //______________________________________________________________________________
0275 template <typename Architecture_t>
0276 TConvLayer<Architecture_t>::TConvLayer(const TConvLayer &convLayer)
0277    :  VGeneralLayer<Architecture_t>(convLayer), fFilterDepth(convLayer.fFilterDepth),
0278       fFilterHeight(convLayer.fFilterHeight), fFilterWidth(convLayer.fFilterWidth), fStrideRows(convLayer.fStrideRows),
0279       fStrideCols(convLayer.fStrideCols), fNLocalViewPixels(convLayer.fNLocalViewPixels),
0280       fNLocalViews(convLayer.fNLocalViews), fDropoutProbability(convLayer.fDropoutProbability),
0281       fPaddingHeight(convLayer.fPaddingHeight), fPaddingWidth(convLayer.fPaddingWidth),
0282       fInputActivation( convLayer.GetInputActivation().GetShape() ),
0283       fF(convLayer.fF),
0284       fReg(convLayer.fReg), fWeightDecay(convLayer.fWeightDecay),
0285       fForwardTensor( convLayer.GetForwardMatrices().GetShape() )
0286 {
0287    InitializeDescriptors();
0288    InitializeWorkspace();
0289 }
0290 
0291 //______________________________________________________________________________
0292 //FIXME: Add function for cudaFree
0293 template <typename Architecture_t>
0294 TConvLayer<Architecture_t>::~TConvLayer()
0295 {
0296    //std::cout << "!!!!Delete conv layer " << this->GetOutput().GetShape()[1] << "  " << this->GetOutput().GetShape()[2] << "  " << this->GetOutput().GetShape()[3] << std::endl;
0297    if (fDescriptors) {
0298       ReleaseDescriptors();
0299       delete fDescriptors;
0300    }
0301 
0302    if (fWorkspace) {
0303       FreeWorkspace();
0304       delete fWorkspace;
0305    }
0306 }
0307 
0308 
0309 //______________________________________________________________________________
0310 template <typename Architecture_t>
0311 auto TConvLayer<Architecture_t>::Forward(Tensor_t &input, bool /*applyDropout*/) -> void
0312 {
0313    TConvParams params(this->GetBatchSize(), this->GetInputDepth(), this->GetInputHeight(), this->GetInputWidth(),
0314                       this->GetDepth(), this->GetFilterHeight(), this->GetFilterWidth(),
0315                       this->GetStrideRows(), this->GetStrideCols(), this->GetPaddingHeight(), this->GetPaddingWidth());
0316 
0317    //R__ASSERT( input.size() > 0);
0318    Architecture_t::ConvLayerForward(this->GetOutput(), this->GetInputActivation(), input, this->GetWeightsAt(0),
0319                                     this->GetBiasesAt(0), params, this->GetActivationFunction(),
0320                                     this->GetForwardMatrices(), (TCNNDescriptors<TConvLayer<Architecture_t>> &) (*fDescriptors),
0321                                     (TCNNWorkspace<TConvLayer<Architecture_t>> &) (*fWorkspace));
0322 }
0323 
0324 //______________________________________________________________________________
0325 template <typename Architecture_t>
0326 auto TConvLayer<Architecture_t>::Backward(Tensor_t &gradients_backward,
0327                                           const Tensor_t &activations_backward) -> void
0328 //                                          Tensor_t & /*inp1*/, Tensor_t &
0329 //                                          /*inp2*/) -> void
0330 {
0331    Architecture_t::ConvLayerBackward(
0332       gradients_backward, this->GetWeightGradientsAt(0), this->GetBiasGradientsAt(0), this->GetInputActivation(),
0333       this->GetActivationGradients(), this->GetWeightsAt(0), activations_backward, this->GetOutput(),
0334       this->GetActivationFunction(),
0335       (TCNNDescriptors<TConvLayer<Architecture_t>> &) (*fDescriptors),
0336       (TCNNWorkspace<TConvLayer<Architecture_t>> &) (*fWorkspace),
0337       this->GetBatchSize(), this->GetInputHeight(), this->GetInputWidth(), this->GetDepth(),
0338       this->GetHeight(), this->GetWidth(), this->GetFilterDepth(), this->GetFilterHeight(),
0339       this->GetFilterWidth(), this->GetNLocalViews());
0340 
0341    addRegularizationGradients<Architecture_t>(this->GetWeightGradientsAt(0), this->GetWeightsAt(0),
0342                                               this->GetWeightDecay(), this->GetRegularization());
0343 }
0344 
0345 //______________________________________________________________________________
0346 template <typename Architecture_t>
0347 auto TConvLayer<Architecture_t>::Print() const -> void
0348 {
0349    std::cout << " CONV LAYER: \t";
0350    std::cout << "( W = " << this->GetWidth() << " , ";
0351    std::cout << " H = " << this->GetHeight() << " , ";
0352    std::cout << " D = " << this->GetDepth() << " ) ";
0353 
0354    std::cout << "\t Filter ( W = " << this->GetFilterWidth() << " , ";
0355    std::cout << " H = " << this->GetFilterHeight() << " ) ";
0356    //std::cout << "\t Local Views = " << this->GetNLocalViews()  << " " ;
0357    if (this->GetOutput().GetSize() > 0) {
0358       std::cout << "\tOutput = ( " << this->GetOutput().GetFirstSize() << " , "
0359                 << this->GetOutput().GetCSize() << " , " << this->GetOutput().GetHSize() << " , " << this->GetOutput().GetWSize()
0360                 << " ) ";
0361    }
0362    std::vector<std::string> activationNames = { "Identity","Relu","Sigmoid","Tanh","SymmRelu","SoftSign","Gauss" };
0363    std::cout << "\t Activation Function = ";
0364    std::cout << activationNames[ static_cast<int>(fF) ] << std::endl;
0365 }
0366 
0367 //______________________________________________________________________________
0368 template <typename Architecture_t>
0369 void TConvLayer<Architecture_t>::AddWeightsXMLTo(void *parent)
0370 {
0371    auto layerxml = gTools().xmlengine().NewChild(parent, nullptr, "ConvLayer");
0372 
0373    gTools().xmlengine().NewAttr(layerxml, nullptr, "Depth", gTools().StringFromInt(this->GetDepth()));
0374    gTools().xmlengine().NewAttr(layerxml, nullptr, "FilterHeight", gTools().StringFromInt(this->GetFilterHeight()));
0375    gTools().xmlengine().NewAttr(layerxml, nullptr, "FilterWidth", gTools().StringFromInt(this->GetFilterWidth()));
0376    gTools().xmlengine().NewAttr(layerxml, nullptr, "StrideRows", gTools().StringFromInt(this->GetStrideRows()));
0377    gTools().xmlengine().NewAttr(layerxml, nullptr, "StrideCols", gTools().StringFromInt(this->GetStrideCols()));
0378    gTools().xmlengine().NewAttr(layerxml, nullptr, "PaddingHeight", gTools().StringFromInt(this->GetPaddingHeight()));
0379    gTools().xmlengine().NewAttr(layerxml, nullptr, "PaddingWidth", gTools().StringFromInt(this->GetPaddingWidth()));
0380 
0381 
0382    int activationFunction = static_cast<int>(this -> GetActivationFunction());
0383    gTools().xmlengine().NewAttr(layerxml, nullptr, "ActivationFunction",
0384                                 TString::Itoa(activationFunction, 10));
0385 
0386    // write weights and bias matrix
0387    this->WriteMatrixToXML(layerxml, "Weights", this -> GetWeightsAt(0));
0388    this->WriteMatrixToXML(layerxml, "Biases",  this -> GetBiasesAt(0));
0389 }
0390 
0391 //______________________________________________________________________________
0392 template <typename Architecture_t>
0393 void TConvLayer<Architecture_t>::ReadWeightsFromXML(void *parent)
0394 {
0395    // read weights and biases
0396    // the meta information is read before because it is needed before creating the Conv layer
0397    this->ReadMatrixXML(parent,"Weights", this -> GetWeightsAt(0));
0398    this->ReadMatrixXML(parent,"Biases", this -> GetBiasesAt(0));
0399 }
0400 
0401 template <typename Architecture_t>
0402 size_t TConvLayer<Architecture_t>::calculateDimension(size_t imgDim, size_t fltDim, size_t padding, size_t stride)
0403 {
0404    size_t temp = imgDim - fltDim + 2 * padding;
0405    if (temp % stride || temp + stride <= 0) {
0406       Fatal("calculateDimension", "Not compatible hyper parameters for layer - (imageDim, filterDim, padding, stride) "
0407             "%zu, %zu, %zu, %zu", imgDim, fltDim, padding, stride);
0408    }
0409    return temp / stride + 1;
0410 }
0411 
0412 template <typename Architecture_t>
0413 size_t TConvLayer<Architecture_t>::calculateNLocalViews(size_t inputHeight, size_t filterHeight, size_t paddingHeight,
0414                                                         size_t strideRows, size_t inputWidth, size_t filterWidth,
0415                                                         size_t paddingWidth, size_t strideCols)
0416 {
0417     int height = calculateDimension(inputHeight, filterHeight, paddingHeight, strideRows);
0418     int width = calculateDimension(inputWidth, filterWidth, paddingWidth, strideCols);
0419 
0420     return height * width;
0421 }
0422 
0423 //______________________________________________________________________________
0424 template <typename Architecture_t>
0425 void TConvLayer<Architecture_t>::InitializeDescriptors() {
0426    Architecture_t::InitializeConvDescriptors(fDescriptors, this);
0427 }
0428 
0429 template <typename Architecture_t>
0430 void TConvLayer<Architecture_t>::ReleaseDescriptors() {
0431    Architecture_t::ReleaseConvDescriptors(fDescriptors);
0432 }
0433 
0434 //______________________________________________________________________________
0435 template <typename Architecture_t>
0436 void TConvLayer<Architecture_t>::InitializeWorkspace() {
0437    TConvParams params(this->GetBatchSize(), this->GetInputDepth(), this->GetInputHeight(), this->GetInputWidth(),
0438                       this->GetDepth(), this->GetFilterHeight(), this->GetFilterWidth(),
0439                       this->GetStrideRows(), this->GetStrideCols(), this->GetPaddingHeight(), this->GetPaddingWidth());
0440 
0441    Architecture_t::InitializeConvWorkspace(fWorkspace, fDescriptors, params, this);
0442 }
0443 
0444 template <typename Architecture_t>
0445 void TConvLayer<Architecture_t>::FreeWorkspace() {
0446    Architecture_t::FreeConvWorkspace(fWorkspace);
0447 }
0448 
0449 //______________________________________________________________________________
0450 
0451 } // namespace CNN
0452 } // namespace DNN
0453 } // namespace TMVA
0454 
0455 #endif