27 #ifndef TMVA_CNN_CONVLAYER 
   28 #define TMVA_CNN_CONVLAYER 
   43 typedef struct TConvParams {
 
   61    TConvParams(
size_t _batchSize, 
size_t _inputDepth, 
size_t _inputHeight, 
size_t _inputWidth, 
size_t _numberFilters,
 
   62                size_t _filterHeight, 
size_t _filterWidth, 
size_t _strideRows, 
size_t _strideCols,
 
   63                size_t _paddingHeight, 
size_t _paddingWidth)
 
   64            : batchSize(_batchSize), inputDepth(_inputDepth), inputHeight(_inputHeight), inputWidth(_inputWidth),
 
   65              numberFilters(_numberFilters), filterHeight(_filterHeight), filterWidth(_filterWidth),
 
   66              strideRows(_strideRows), strideCols(_strideCols), paddingHeight(_paddingHeight),
 
   67              paddingWidth(_paddingWidth)
 
   73 template <
typename Architecture_t>
 
   74 class TConvLayer : 
public VGeneralLayer<Architecture_t> {
 
   76    using Tensor_t = 
typename Architecture_t::Tensor_t;
 
   77    using Matrix_t = 
typename Architecture_t::Matrix_t;
 
   78    using Scalar_t = 
typename Architecture_t::Scalar_t;
 
   80    using LayerDescriptor_t   = 
typename Architecture_t::ConvolutionDescriptor_t;
 
   81    using WeightsDescriptor_t = 
typename Architecture_t::FilterDescriptor_t;
 
   82    using HelperDescriptor_t  = 
typename Architecture_t::ActivationDescriptor_t;
 
   84    using AlgorithmForward_t  = 
typename Architecture_t::AlgorithmForward_t;  
 
   85    using AlgorithmBackward_t = 
typename Architecture_t::AlgorithmBackward_t; 
 
   86    using AlgorithmHelper_t   = 
typename Architecture_t::AlgorithmHelper_t;   
 
   87    using ReduceTensorDescriptor_t = 
typename Architecture_t::ReduceTensorDescriptor_t; 
 
   90    using AlgorithmDataType_t = 
typename Architecture_t::AlgorithmDataType_t;
 
   93    static size_t calculateDimension(
size_t imgDim, 
size_t fltDim, 
size_t padding, 
size_t stride);
 
   96    static size_t inline calculateNLocalViewPixels(
size_t depth, 
size_t height, 
size_t width) { 
return depth * height * width; }
 
   99    static size_t calculateNLocalViews(
size_t inputHeight, 
size_t filterHeight, 
size_t paddingHeight, 
size_t strideRows,
 
  100                                size_t inputWidth, 
size_t filterWidth, 
size_t paddingWidth, 
size_t strideCols);
 
  104    size_t fFilterHeight; 
 
  110    size_t fNLocalViewPixels;     
 
  113    Scalar_t fDropoutProbability; 
 
  115    TDescriptors * fDescriptors = 
nullptr;  
 
  117    TWorkspace * fWorkspace = 
nullptr;
 
  119    size_t fPaddingHeight;        
 
  120    size_t fPaddingWidth;         
 
  122    Tensor_t fInputActivation;        
 
  124    std::vector<int> fBackwardIndices;  
 
  126    EActivationFunction fF;             
 
  127    ERegularization fReg;               
 
  128    Scalar_t fWeightDecay;              
 
  130    Tensor_t fForwardTensor;            
 
  132    void InitializeDescriptors();
 
  133    void ReleaseDescriptors();
 
  134    void InitializeWorkspace();
 
  135    void FreeWorkspace();
 
  139    TConvLayer(
size_t BatchSize, 
size_t InputDepth, 
size_t InputHeight, 
size_t InputWidth, 
size_t Depth, EInitialization Init,
 
  140               size_t FilterHeight, 
size_t FilterWidth, 
size_t StrideRows, 
size_t StrideCols, 
size_t PaddingHeight,
 
  141               size_t PaddingWidth, Scalar_t DropoutProbability, EActivationFunction f, ERegularization Reg,
 
  142               Scalar_t WeightDecay);
 
  145    TConvLayer(TConvLayer<Architecture_t> *layer);
 
  148    TConvLayer(
const TConvLayer &);
 
  151    virtual ~TConvLayer();
 
  160    void Forward(Tensor_t &input, 
bool applyDropout = 
false);
 
  166    void Backward(Tensor_t &gradients_backward, 
const Tensor_t &activations_backward);
 
  173    virtual void AddWeightsXMLTo(
void *parent);
 
  176    virtual void ReadWeightsFromXML(
void *parent);
 
  179    size_t GetFilterDepth()
 const { 
return fFilterDepth; }
 
  180    size_t GetFilterHeight()
 const { 
return fFilterHeight; }
 
  181    size_t GetFilterWidth()
 const { 
return fFilterWidth; }
 
  183    size_t GetStrideRows()
 const { 
return fStrideRows; }
 
  184    size_t GetStrideCols()
 const { 
return fStrideCols; }
 
  186    size_t GetPaddingHeight()
 const { 
return fPaddingHeight; }
 
  187    size_t GetPaddingWidth()
 const { 
return fPaddingWidth; }
 
  189    size_t GetNLocalViewPixels()
 const { 
return fNLocalViewPixels; }
 
  190    size_t GetNLocalViews()
 const { 
return fNLocalViews; }
 
  192    Scalar_t GetDropoutProbability()
 const { 
return fDropoutProbability; }
 
  194    const Tensor_t &GetInputActivation()
 const { 
return fInputActivation; }
 
  195    Tensor_t &GetInputActivation() { 
return fInputActivation; }
 
  197    Matrix_t &GetInputActivationAt(
size_t i) { 
return fInputActivation[i]; }
 
  198    const Matrix_t &GetInputActivationAt(
size_t i)
 const { 
return fInputActivation[i]; }
 
  200    const Tensor_t &GetForwardMatrices()
 const { 
return fForwardTensor; }
 
  201    Tensor_t &GetForwardMatrices() { 
return fForwardTensor; }
 
  203    EActivationFunction GetActivationFunction()
 const { 
return fF; }
 
  204    ERegularization GetRegularization()
 const { 
return fReg; }
 
  205    Scalar_t GetWeightDecay()
 const { 
return fWeightDecay; }
 
  208    TDescriptors * GetDescriptors() {
return fDescriptors;}
 
  209    const TDescriptors * GetDescriptors()
 const {
return fDescriptors;}
 
  211    TWorkspace * GetWorkspace() {
return fWorkspace;}
 
  212    const TWorkspace * GetWorkspace()
 const {
return fWorkspace;}
 
  220 template <
typename Architecture_t>
 
  221 TConvLayer<Architecture_t>::TConvLayer(
size_t batchSize, 
size_t inputDepth, 
size_t inputHeight, 
size_t inputWidth,
 
  222                                        size_t depth, EInitialization init, 
size_t filterHeight, 
size_t filterWidth,
 
  223                                        size_t strideRows, 
size_t strideCols, 
size_t paddingHeight, 
size_t paddingWidth,
 
  224                                        Scalar_t dropoutProbability, EActivationFunction f, ERegularization reg,
 
  225                                        Scalar_t weightDecay)
 
  226    : VGeneralLayer<Architecture_t>(batchSize, inputDepth, inputHeight, inputWidth, depth,
 
  227                                    calculateDimension(inputHeight, filterHeight, paddingHeight, strideRows),
 
  228                                    calculateDimension(inputWidth, filterWidth, paddingWidth, strideCols),
 
  229                                    1, depth, calculateNLocalViewPixels(inputDepth, filterHeight, filterWidth),
 
  230                                    1, depth, 1, batchSize, depth,
 
  231                                    calculateNLocalViews(inputHeight, filterHeight, paddingHeight, strideRows,
 
  232                                                         inputWidth, filterWidth, paddingWidth, strideCols),
 
  234      fFilterDepth(inputDepth), fFilterHeight(filterHeight), fFilterWidth(filterWidth), fStrideRows(strideRows),
 
  235      fStrideCols(strideCols), fNLocalViewPixels(calculateNLocalViewPixels(inputDepth, filterHeight, filterWidth)),
 
  236      fNLocalViews(calculateNLocalViews(inputHeight, filterHeight, paddingHeight, strideRows,
 
  237                                        inputWidth, filterWidth, paddingWidth, strideCols)),
 
  238      fDropoutProbability(dropoutProbability), fPaddingHeight(paddingHeight), fPaddingWidth(paddingWidth),
 
  239      fInputActivation(), fF(f), fReg(reg), fWeightDecay(weightDecay)
 
  246    fInputActivation = Tensor_t( batchSize, depth, fNLocalViews);     
 
  247    fForwardTensor = Tensor_t ( batchSize, fNLocalViews, fNLocalViewPixels );
 
  250    InitializeDescriptors();
 
  251    InitializeWorkspace();
 
  255 template <
typename Architecture_t>
 
  256 TConvLayer<Architecture_t>::TConvLayer(TConvLayer<Architecture_t> *layer)
 
  257    : VGeneralLayer<Architecture_t>(layer), fFilterDepth(layer->GetFilterDepth()),
 
  258      fFilterHeight(layer->GetFilterHeight()), fFilterWidth(layer->GetFilterWidth()),
 
  259      fStrideRows(layer->GetStrideRows()), fStrideCols(layer->GetStrideCols()),
 
  260      fNLocalViewPixels(layer->GetNLocalViewPixels()), fNLocalViews(layer->GetNLocalViews()),
 
  261      fDropoutProbability(layer->GetDropoutProbability()), fPaddingHeight(layer->GetPaddingHeight()),
 
  262      fPaddingWidth(layer->GetPaddingWidth()),
 
  263      fInputActivation( layer->GetInputActivation().GetShape() ),
 
  264      fF(layer->GetActivationFunction()),
 
  265      fReg(layer->GetRegularization()), fWeightDecay(layer->GetWeightDecay()),
 
  266      fForwardTensor( layer->GetForwardMatrices().GetShape() )
 
  268    InitializeDescriptors();
 
  269    InitializeWorkspace();
 
  274 template <
typename Architecture_t>
 
  275 TConvLayer<Architecture_t>::TConvLayer(
const TConvLayer &convLayer)
 
  276    :  VGeneralLayer<Architecture_t>(convLayer), fFilterDepth(convLayer.fFilterDepth),
 
  277       fFilterHeight(convLayer.fFilterHeight), fFilterWidth(convLayer.fFilterWidth), fStrideRows(convLayer.fStrideRows),
 
  278       fStrideCols(convLayer.fStrideCols), fNLocalViewPixels(convLayer.fNLocalViewPixels),
 
  279       fNLocalViews(convLayer.fNLocalViews), fDropoutProbability(convLayer.fDropoutProbability),
 
  280       fPaddingHeight(convLayer.fPaddingHeight), fPaddingWidth(convLayer.fPaddingWidth),
 
  281       fInputActivation( convLayer.GetInputActivation().GetShape() ),
 
  283       fReg(convLayer.fReg), fWeightDecay(convLayer.fWeightDecay),
 
  284       fForwardTensor( convLayer.GetForwardMatrices().GetShape() )
 
  286    InitializeDescriptors();
 
  287    InitializeWorkspace();
 
  292 template <
typename Architecture_t>
 
  293 TConvLayer<Architecture_t>::~TConvLayer()
 
  297       ReleaseDescriptors();
 
  309 template <
typename Architecture_t>
 
  310 auto TConvLayer<Architecture_t>::Forward(Tensor_t &input, 
bool ) -> 
void 
  312    TConvParams params(this->GetBatchSize(), this->GetInputDepth(), this->GetInputHeight(), this->GetInputWidth(),
 
  313                       this->GetDepth(), this->GetFilterHeight(), this->GetFilterWidth(),
 
  314                       this->GetStrideRows(), this->GetStrideCols(), this->GetPaddingHeight(), this->GetPaddingWidth());
 
  317    Architecture_t::ConvLayerForward(this->GetOutput(), this->GetInputActivation(), input, this->GetWeightsAt(0),
 
  318                                     this->GetBiasesAt(0), params, this->GetActivationFunction(),
 
  319                                     this->GetForwardMatrices(), (TCNNDescriptors<TConvLayer<Architecture_t>> &) (*fDescriptors),
 
  320                                     (TCNNWorkspace<TConvLayer<Architecture_t>> &) (*fWorkspace));
 
  324 template <
typename Architecture_t>
 
  325 auto TConvLayer<Architecture_t>::Backward(Tensor_t &gradients_backward,
 
  326                                           const Tensor_t &activations_backward) -> 
void 
  330    Architecture_t::ConvLayerBackward(
 
  331       gradients_backward, this->GetWeightGradientsAt(0), this->GetBiasGradientsAt(0), this->GetInputActivation(),
 
  332       this->GetActivationGradients(), this->GetWeightsAt(0), activations_backward, this->GetOutput(),
 
  333       this->GetActivationFunction(),
 
  334       (TCNNDescriptors<TConvLayer<Architecture_t>> &) (*fDescriptors),
 
  335       (TCNNWorkspace<TConvLayer<Architecture_t>> &) (*fWorkspace),
 
  336       this->GetBatchSize(), this->GetInputHeight(), this->GetInputWidth(), this->GetDepth(),
 
  337       this->GetHeight(), this->GetWidth(), this->GetFilterDepth(), this->GetFilterHeight(),
 
  338       this->GetFilterWidth(), this->GetNLocalViews());
 
  340    addRegularizationGradients<Architecture_t>(this->GetWeightGradientsAt(0), this->GetWeightsAt(0),
 
  341                                               this->GetWeightDecay(), this->GetRegularization());
 
  345 template <
typename Architecture_t>
 
  346 auto TConvLayer<Architecture_t>::Print() const -> 
void 
  348    std::cout << 
" CONV LAYER: \t";
 
  349    std::cout << 
"( W = " << this->GetWidth() << 
" , ";
 
  350    std::cout << 
" H = " << this->GetHeight() << 
" , ";
 
  351    std::cout << 
" D = " << this->GetDepth() << 
" ) ";
 
  353    std::cout << 
"\t Filter ( W = " << this->GetFilterWidth() << 
" , ";
 
  354    std::cout << 
" H = " << this->GetFilterHeight() << 
" ) ";
 
  356    if (this->GetOutput().GetSize() > 0) {
 
  357       std::cout << 
"\tOutput = ( " << this->GetOutput().GetFirstSize() << 
" , " 
  358                 << this->GetOutput().GetCSize() << 
" , " << this->GetOutput().GetHSize() << 
" , " << this->GetOutput().GetWSize()
 
  361    std::vector<std::string> activationNames = { 
"Identity",
"Relu",
"Sigmoid",
"Tanh",
"SymmRelu",
"SoftSign",
"Gauss" };
 
  362    std::cout << 
"\t Activation Function = ";
 
  363    std::cout << activationNames[ static_cast<int>(fF) ] << std::endl;
 
  367 template <
typename Architecture_t>
 
  368 void TConvLayer<Architecture_t>::AddWeightsXMLTo(
void *parent)
 
  370    auto layerxml = gTools().xmlengine().NewChild(parent, 0, 
"ConvLayer");
 
  372    gTools().xmlengine().NewAttr(layerxml, 0, 
"Depth", gTools().StringFromInt(this->GetDepth()));
 
  373    gTools().xmlengine().NewAttr(layerxml, 0, 
"FilterHeight", gTools().StringFromInt(this->GetFilterHeight()));
 
  374    gTools().xmlengine().NewAttr(layerxml, 0, 
"FilterWidth", gTools().StringFromInt(this->GetFilterWidth()));
 
  375    gTools().xmlengine().NewAttr(layerxml, 0, 
"StrideRows", gTools().StringFromInt(this->GetStrideRows()));
 
  376    gTools().xmlengine().NewAttr(layerxml, 0, 
"StrideCols", gTools().StringFromInt(this->GetStrideCols()));
 
  377    gTools().xmlengine().NewAttr(layerxml, 0, 
"PaddingHeight", gTools().StringFromInt(this->GetPaddingHeight()));
 
  378    gTools().xmlengine().NewAttr(layerxml, 0, 
"PaddingWidth", gTools().StringFromInt(this->GetPaddingWidth()));
 
  381    int activationFunction = 
static_cast<int>(
this -> GetActivationFunction());
 
  382    gTools().xmlengine().NewAttr(layerxml, 0, 
"ActivationFunction",
 
  383                                 TString::Itoa(activationFunction, 10));
 
  386    this->WriteMatrixToXML(layerxml, 
"Weights", 
this -> GetWeightsAt(0));
 
  387    this->WriteMatrixToXML(layerxml, 
"Biases",  
this -> GetBiasesAt(0));
 
  391 template <
typename Architecture_t>
 
  392 void TConvLayer<Architecture_t>::ReadWeightsFromXML(
void *parent)
 
  396    this->ReadMatrixXML(parent,
"Weights", 
this -> GetWeightsAt(0));
 
  397    this->ReadMatrixXML(parent,
"Biases", 
this -> GetBiasesAt(0));
 
  400 template <
typename Architecture_t>
 
  401 size_t TConvLayer<Architecture_t>::calculateDimension(
size_t imgDim, 
size_t fltDim, 
size_t padding, 
size_t stride)
 
  403    size_t temp = imgDim - fltDim + 2 * padding;
 
  404    if (temp % stride || temp + stride <= 0) {
 
  405       Fatal(
"calculateDimension", 
"Not compatible hyper parameters for layer - (imageDim, filterDim, padding, stride) " 
  406             "%zu, %zu, %zu, %zu", imgDim, fltDim, padding, stride);
 
  408    return temp / stride + 1;
 
  411 template <
typename Architecture_t>
 
  412 size_t TConvLayer<Architecture_t>::calculateNLocalViews(
size_t inputHeight, 
size_t filterHeight, 
size_t paddingHeight,
 
  413                                                         size_t strideRows, 
size_t inputWidth, 
size_t filterWidth,
 
  414                                                         size_t paddingWidth, 
size_t strideCols)
 
  416     int height = calculateDimension(inputHeight, filterHeight, paddingHeight, strideRows);
 
  417     int width = calculateDimension(inputWidth, filterWidth, paddingWidth, strideCols);
 
  419     return height * width;
 
  423 template <
typename Architecture_t>
 
  424 void TConvLayer<Architecture_t>::InitializeDescriptors() {
 
  425    Architecture_t::InitializeConvDescriptors(fDescriptors, 
this);
 
  428 template <
typename Architecture_t>
 
  429 void TConvLayer<Architecture_t>::ReleaseDescriptors() {
 
  430    Architecture_t::ReleaseConvDescriptors(fDescriptors);
 
  434 template <
typename Architecture_t>
 
  435 void TConvLayer<Architecture_t>::InitializeWorkspace() {
 
  436    TConvParams params(this->GetBatchSize(), this->GetInputDepth(), this->GetInputHeight(), this->GetInputWidth(),
 
  437                       this->GetDepth(), this->GetFilterHeight(), this->GetFilterWidth(),
 
  438                       this->GetStrideRows(), this->GetStrideCols(), this->GetPaddingHeight(), this->GetPaddingWidth());
 
  440    Architecture_t::InitializeConvWorkspace(fWorkspace, fDescriptors, params, 
this);
 
  443 template <
typename Architecture_t>
 
  444 void TConvLayer<Architecture_t>::FreeWorkspace() {
 
  445    Architecture_t::FreeConvWorkspace(fWorkspace, 
this);