in sparseconvnet/SCN/CPU/BatchNormalization.cpp [13:62]
void BatchNormalization_ForwardPass(T *input_features, T *output_features,
Int nPlanes, Int input_stride,
Int output_stride, Int nActive, T *saveMean,
T *saveInvStd, T *runningMean,
T *runningVar, T *weight, T *bias, T eps,
T momentum, bool train, T leakiness) {
if (train) {
std::memset(saveMean, 0, nPlanes * sizeof(T));
std::memset(saveInvStd, 0, nPlanes * sizeof(T));
for (Int row = 0; row < nActive; row++) {
Int ci = row * input_stride;
for (Int plane = 0; plane < nPlanes; plane++, ci++) {
T ifci = input_features[ci];
saveMean[plane] += ifci;
saveInvStd[plane] += ifci * ifci; // accumulate sum-squares
// before inverse square
// rooting
}
}
for (Int plane = 0; plane < nPlanes; plane++) {
saveMean[plane] /= nActive;
runningMean[plane] =
momentum * runningMean[plane] + (1 - momentum) * saveMean[plane];
saveInvStd[plane] -= saveMean[plane] * saveMean[plane] * nActive;
runningVar[plane] = momentum * runningVar[plane] +
(1 - momentum) * saveInvStd[plane] / (nActive - 1);
saveInvStd[plane] = powf(saveInvStd[plane] / nActive + eps, -0.5);
}
} else {
for (Int plane = 0; plane < nPlanes; plane++) {
saveMean[plane] = runningMean[plane];
saveInvStd[plane] = powf(runningVar[plane] + eps, -0.5);
}
}
std::vector<T> w(nPlanes);
std::vector<T> b(nPlanes);
for (Int plane = 0; plane < nPlanes; plane++) {
w[plane] = saveInvStd[plane] * (weight ? weight[plane] : 1);
b[plane] = -saveMean[plane] * w[plane] + (bias ? bias[plane] : 0);
}
for (Int row = 0; row < nActive; row++) {
Int ci = row * input_stride;
Int co = row * output_stride;
for (Int plane = 0; plane < nPlanes; plane++, ci++, co++) {
T out = input_features[ci] * w[plane] + b[plane];
const T r = (out > 0) ? 1 : leakiness;
output_features[co] = out * r;
}
}
}