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);