22 template <
typename AReal>
23 void TReference<AReal>::MultiplyTranspose(TMatrixT<AReal> &output,
const TMatrixT<AReal> &input,
24 const TMatrixT<AReal> &weights)
26 output.MultT(input, weights);
29 template <
typename AReal>
30 void TReference<AReal>::AddRowWise(TMatrixT<AReal> &output,
const TMatrixT<AReal> &biases)
32 for (
size_t i = 0; i < (size_t)output.GetNrows(); i++) {
33 for (
size_t j = 0; j < (size_t)output.GetNcols(); j++) {
34 output(i, j) += biases(j, 0);
39 template <
typename AReal>
40 void TReference<AReal>::Backward(TMatrixT<AReal> &activation_gradients_backward, TMatrixT<AReal> &weight_gradients,
41 TMatrixT<AReal> &bias_gradients, TMatrixT<AReal> &df,
42 const TMatrixT<AReal> &activation_gradients,
const TMatrixT<AReal> &weights,
43 const TMatrixT<AReal> &activations_backward)
47 for (
size_t i = 0; i < (size_t)df.GetNrows(); i++) {
48 for (
size_t j = 0; j < (size_t)df.GetNcols(); j++) {
49 df(i, j) *= activation_gradients(i, j);
54 if (activation_gradients_backward.GetNoElements() > 0) {
55 activation_gradients_backward.Mult(df, weights);
59 if (weight_gradients.GetNoElements() > 0) {
60 weight_gradients.TMult(df, activations_backward);
64 if (bias_gradients.GetNoElements() > 0) {
65 for (
size_t j = 0; j < (size_t)df.GetNcols(); j++) {
67 for (
size_t i = 0; i < (size_t)df.GetNrows(); i++) {
70 bias_gradients(j, 0) = sum;
75 template <
typename AReal>
76 void TReference<AReal>::ScaleAdd(TMatrixT<AReal> &A,
const TMatrixT<AReal> &B, AReal beta)
78 for (
size_t i = 0; i < (size_t)A.GetNrows(); i++) {
79 for (
size_t j = 0; j < (size_t)A.GetNcols(); j++) {
80 A(i, j) += beta * B(i, j);
85 template <
typename AReal>
86 void TReference<AReal>::Copy(TMatrixT<AReal> &A,
const TMatrixT<AReal> &B)
91 template <
typename AReal>
92 void TReference<AReal>::ScaleAdd(std::vector<TMatrixT<AReal>> &A,
const std::vector<TMatrixT<AReal>> &B, AReal beta)
94 for (
size_t i = 0; i < A.size(); ++i) {
95 ScaleAdd(A[i], B[i], beta);
99 template <
typename AReal>
100 void TReference<AReal>::Copy(std::vector<TMatrixT<AReal>> &A,
const std::vector<TMatrixT<AReal>> &B)
102 for (
size_t i = 0; i < A.size(); ++i) {
108 template <
typename AReal>
109 void TReference<AReal>::Im2col(TMatrixT<AReal> &A,
const TMatrixT<AReal> &B,
size_t imgHeight,
size_t imgWidth,
110 size_t fltHeight,
size_t fltWidth,
size_t strideRows,
size_t strideCols,
111 size_t zeroPaddingHeight,
size_t zeroPaddingWidth)
114 int imgHeightBound = imgHeight + zeroPaddingHeight - (fltHeight - 1) / 2 - 1;
115 int imgWidthBound = imgWidth + zeroPaddingWidth - (fltWidth - 1) / 2 - 1;
116 size_t currLocalView = 0;
119 for (
int i = -zeroPaddingHeight + fltHeight / 2; i <= imgHeightBound; i += strideRows) {
120 for (
int j = -zeroPaddingWidth + fltWidth / 2; j <= imgWidthBound; j += strideCols) {
121 size_t currLocalViewPixel = 0;
124 for (
int m = 0; m < B.GetNrows(); m++) {
125 for (Int_t k = i - Int_t(fltHeight) / 2; k <= i + (Int_t(fltHeight) - 1) / 2; k++) {
126 for (Int_t l = j - Int_t(fltWidth) / 2; l <= j + (Int_t(fltWidth) - 1) / 2; l++) {
129 if (k < 0 || k >= Int_t(imgHeight) || l < 0 || l >= Int_t(imgWidth))
130 A(currLocalView, currLocalViewPixel++) = 0;
132 A(currLocalView, currLocalViewPixel++) = B(m, k * imgWidth + l);
143 template <
typename AReal>
144 void TReference<AReal>::RotateWeights(TMatrixT<AReal> &A,
const TMatrixT<AReal> &B,
size_t filterDepth,
145 size_t filterHeight,
size_t filterWidth,
size_t numFilters)
147 size_t jump = filterHeight * filterWidth;
148 for (
size_t j = 0; j < filterDepth; j++) {
149 for (
size_t k = 0; k < numFilters; k++) {
150 for (
size_t i = 0; i < jump; i++) {
151 A(j, k * jump + i) = B(k, ((j + 1) * jump - 1) - i);
158 template <
typename AReal>
159 void TReference<AReal>::AddConvBiases(TMatrixT<AReal> &output,
const TMatrixT<AReal> &biases)
161 for (
size_t i = 0; i < (size_t)output.GetNrows(); i++) {
162 for (
size_t j = 0; j < (size_t)output.GetNcols(); j++) {
163 output(i, j) += biases(i, 0);
168 #ifdef HAVE_CNN_REFERENCE
170 template <
typename AReal>
171 void TReference<AReal>::ConvLayerBackward(std::vector<TMatrixT<AReal>> &activation_gradients_backward,
172 TMatrixT<AReal> &weight_gradients, TMatrixT<AReal> &bias_gradients,
173 std::vector<TMatrixT<AReal>> &df,
174 const std::vector<TMatrixT<AReal>> &activation_gradients,
175 const TMatrixT<AReal> &weights,
176 const std::vector<TMatrixT<AReal>> &activations_backward,
size_t batchSize,
177 size_t inputHeight,
size_t inputWidth,
size_t depth,
size_t height,
178 size_t width,
size_t filterDepth,
size_t filterHeight,
size_t filterWidth,
184 m = activation_gradients[0].GetNrows();
185 n = activation_gradients[0].GetNcols();
187 for (
size_t i = 0; i < batchSize; i++) {
188 for (
size_t j = 0; j < (size_t)m; j++) {
189 for (
size_t k = 0; k < (size_t)n; k++) {
190 df[i](j, k) *= activation_gradients[i](j, k);
196 CalculateConvActivationGradients(activation_gradients_backward, df, weights, batchSize, inputHeight, inputWidth,
197 depth, height, width, filterDepth, filterHeight, filterWidth);
200 CalculateConvWeightGradients(weight_gradients, df, activations_backward, batchSize, inputHeight, inputWidth, depth,
201 height, width, filterDepth, filterHeight, filterWidth, nLocalViews);
204 CalculateConvBiasGradients(bias_gradients, df, batchSize, depth, nLocalViews);
208 template <
typename AReal>
209 void TReference<AReal>::CalculateConvActivationGradients(std::vector<TMatrixT<AReal>> &activation_gradients_backward,
210 const std::vector<TMatrixT<AReal>> &df,
211 const TMatrixT<AReal> &weights,
size_t batchSize,
212 size_t inputHeight,
size_t inputWidth,
size_t depth,
213 size_t height,
size_t width,
size_t filterDepth,
214 size_t filterHeight,
size_t filterWidth)
217 if (activation_gradients_backward.size() == 0)
return;
220 TMatrixT<AReal> rotWeights(filterDepth, depth * filterHeight * filterWidth);
221 RotateWeights(rotWeights, weights, filterDepth, filterHeight, filterWidth, weights.GetNrows());
224 size_t tempZeroPaddingHeight = (size_t)(floor((inputHeight - height + filterHeight - 1) / 2));
225 size_t tempZeroPaddingWidth = (size_t)(floor((inputWidth - width + filterWidth - 1) / 2));
228 size_t tempNLocalViews = inputHeight * inputWidth;
229 size_t tempNLocalViewPixels = depth * filterHeight * filterWidth;
231 size_t tempStrideRows = 1;
232 size_t tempStrideCols = 1;
235 for (
size_t i = 0; i < batchSize; i++) {
236 TMatrixT<AReal> dfTr(tempNLocalViews, tempNLocalViewPixels);
237 Im2col(dfTr, df[i], inputHeight, inputWidth, filterHeight, filterWidth, tempStrideRows, tempStrideCols,
238 tempZeroPaddingHeight, tempZeroPaddingWidth);
240 activation_gradients_backward[i].MultT(rotWeights, dfTr);
247 template <
typename AReal>
248 void TReference<AReal>::CalculateConvWeightGradients(TMatrixT<AReal> &weight_gradients,
249 const std::vector<TMatrixT<AReal>> &df,
250 const std::vector<TMatrixT<AReal>> &activations_backward,
251 size_t batchSize,
size_t inputHeight,
size_t inputWidth,
252 size_t depth,
size_t height,
size_t width,
size_t filterDepth,
253 size_t filterHeight,
size_t filterWidth,
size_t nLocalViews)
257 for (Int_t i = 0; i < weight_gradients.GetNrows(); i++) {
258 for (Int_t j = 0; j < weight_gradients.GetNcols(); j++) {
259 weight_gradients(i, j) = 0;
262 for (
size_t i = 0; i < batchSize; i++) {
264 size_t tempZeroPaddingHeight = (filterHeight - height + inputHeight - 1) / 2;
265 size_t tempZeroPaddingWidth = (filterWidth - width + inputWidth - 1) / 2;
267 size_t tempNLocalViews = filterHeight * filterWidth;
268 size_t tempNLocalViewPixels = inputHeight * inputWidth;
270 size_t tempStrideRows = 1;
271 size_t tempStrideCols = 1;
273 for (
size_t j = 0; j < depth; j++) {
276 TMatrixT<AReal> rowDelta(1, nLocalViews);
277 for (
size_t k = 0; k < nLocalViews; k++) {
278 rowDelta(0, k) = df[i](j, k);
282 TMatrixT<AReal> res(filterDepth, filterHeight * filterWidth);
284 TMatrixT<AReal> rowDeltaTr(tempNLocalViews, tempNLocalViewPixels);
285 Im2col(rowDeltaTr, rowDelta, height, width, inputHeight, inputWidth, tempStrideRows, tempStrideCols,
286 tempZeroPaddingHeight, tempZeroPaddingWidth);
288 res.MultT(activations_backward[i], rowDeltaTr);
290 for (
size_t k = 0; k < filterDepth; k++) {
291 for (
size_t l = 0; l < filterHeight * filterWidth; l++) {
292 weight_gradients(j, k * (filterHeight * filterWidth) + l) += res(k, (tempNLocalViews - 1) - l);
299 (void)weight_gradients;
301 (void)activations_backward;
316 template <
typename AReal>
317 void TReference<AReal>::CalculateConvBiasGradients(TMatrixT<AReal> &bias_gradients,
const std::vector<TMatrixT<AReal>> &df,
318 size_t batchSize,
size_t depth,
size_t nLocalViews)
320 for (
size_t i = 0; i < depth; i++) {
322 for (
size_t j = 0; j < nLocalViews; j++) {
323 for (
size_t k = 0; k < batchSize; k++) {
327 bias_gradients(i, 0) = sum;
333 template <
typename AReal>
334 void TReference<AReal>::Downsample(TMatrixT<AReal> &A, TMatrixT<AReal> &B,
const TMatrixT<AReal> &C,
size_t imgHeight,
335 size_t imgWidth,
size_t fltHeight,
size_t fltWidth,
size_t strideRows,
339 int imgHeightBound = imgHeight - (fltHeight - 1) / 2 - 1;
340 int imgWidthBound = imgWidth - (fltWidth - 1) / 2 - 1;
341 size_t currLocalView = 0;
344 for (
int i = fltHeight / 2; i <= imgHeightBound; i += strideRows) {
345 for (
int j = fltWidth / 2; j <= imgWidthBound; j += strideCols) {
347 for (
int m = 0; m < C.GetNrows(); m++) {
348 AReal value = -std::numeric_limits<AReal>::max();
350 for (
int k = i - Int_t(fltHeight) / 2; k <= i + (Int_t(fltHeight) - 1) / 2; k++) {
351 for (
int l = j - Int_t(fltWidth) / 2; l <= j + (Int_t(fltWidth) - 1) / 2; l++) {
352 if (C(m, k * imgWidth + l) > value) {
353 value = C(m, k * imgWidth + l);
354 B(m, currLocalView) = k * imgWidth + l;
358 A(m, currLocalView) = value;
366 template <
typename AReal>
367 void TReference<AReal>::MaxPoolLayerBackward(TMatrixT<AReal> &activationGradientsBackward,
368 const TMatrixT<AReal> &activationGradients,
369 const TMatrixT<AReal> &indexMatrix,
370 size_t ,
size_t ,
size_t ,
371 size_t ,
size_t ,
size_t ,
374 size_t depth = activationGradientsBackward.GetNrows();
376 for (
size_t j = 0; j < depth; j++) {
378 for (
size_t t = 0; t < (size_t)activationGradientsBackward.GetNcols(); t++) {
379 activationGradientsBackward[j][t] = 0;
383 for (
size_t k = 0; k < nLocalViews; k++) {
384 AReal grad = activationGradients[j][k];
385 size_t winningIdx = indexMatrix[j][k];
386 activationGradientsBackward[j][winningIdx] += grad;
392 template <
typename AReal>
393 void TReference<AReal>::Reshape(TMatrixT<AReal> &A,
const TMatrixT<AReal> &B)
395 auto nColsA = A.GetNcols();
396 auto nColsB = B.GetNcols();
398 for (Int_t i = 0; i < A.GetNrows(); i++) {
399 for (Int_t j = 0; j < A.GetNcols(); j++) {
400 auto nElem = i * nColsA + j;
401 A(i, j) = B(nElem / nColsB, nElem % nColsB);
407 template <
typename AReal>
408 void TReference<AReal>::Flatten(TMatrixT<AReal> &A,
const std::vector<TMatrixT<AReal>> &B,
size_t size,
size_t nRows,
411 for (
size_t i = 0; i < (size_t)size; i++) {
412 for (
size_t j = 0; j < (size_t)nRows; j++) {
413 for (
size_t k = 0; k < (size_t)nCols; k++) {
414 A(i, j * nCols + k) = B[i](j, k);
421 template <
typename AReal>
422 void TReference<AReal>::Deflatten(std::vector<TMatrixT<AReal>> &A,
const TMatrixT<AReal> &B,
size_t size,
size_t nRows,
425 for (
size_t i = 0; i < (size_t)size; i++) {
426 for (
size_t j = 0; j < (size_t)nRows; j++) {
427 for (
size_t k = 0; k < (size_t)nCols; k++) {
428 A[i](j, k) = B(i, j * nCols + k);
435 template <
typename AReal>
436 void TReference<AReal>::Rearrange(std::vector<TMatrixT<AReal>> &out,
const std::vector<TMatrixT<AReal>> &in)
440 auto T = out[0].GetNrows();
441 auto D = out[0].GetNcols();
442 if ((T != (Int_t)in.size()) || (Int_t(B) != in[0].GetNrows()) || (D != in[0].GetNcols())) {
443 std::cout <<
"Incompatible Dimensions\n"
444 << in.size() <<
"x" << in[0].GetNrows() <<
"x" << in[0].GetNcols() <<
" --> " << B <<
"x" << T <<
"x"
448 for (
size_t i = 0; i < B; ++i) {
449 for (Int_t j = 0; j < T; ++j) {
450 for (Int_t k = 0; k < D; ++k) {
451 out[i](j, k) = in[j](i, k);