From: Сергей Баранников/AI Tools Lab /SRR/Engineer/삼성전자 Date: Mon, 12 Aug 2019 17:13:27 +0000 (+0300) Subject: [mir_caffe] Refactor importing of BatchNorm (#6467) X-Git-Tag: accepted/tizen/unified/20190903.052428~458 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=da6f204a9f1df051a37392f78a2347c90c31c5e7;p=platform%2Fcore%2Fml%2Fnnfw.git [mir_caffe] Refactor importing of BatchNorm (#6467) Structurize the code, fix comments. Signed-off-by: Sergei Barannikov --- diff --git a/compiler/mir-caffe-importer/caffe_op_creator.cpp b/compiler/mir-caffe-importer/caffe_op_creator.cpp index 0fb0cca..7878ae5 100644 --- a/compiler/mir-caffe-importer/caffe_op_creator.cpp +++ b/compiler/mir-caffe-importer/caffe_op_creator.cpp @@ -634,35 +634,37 @@ std::vector CaffeOpCreator::convertBatchNorm(const caffe::LayerParameter &layer, const std::vector &inputs) { - auto &opts = layer.batch_norm_param(); - float eps = opts.eps(); - auto scale_weight = convertBlob(layer.blobs(2)); - float scale_factor = *reinterpret_cast(scale_weight.at(mir::Index{0})); - // Code below is taken from cpu caffe implementation: - // https://github.com/BVLC/caffe/blob/master/src/caffe/layers/batch_norm_layer.cpp#L100 + const auto &opts = layer.batch_norm_param(); + auto input = inputs[0]; + auto mean_tensor = convertBlob(layer.blobs(0)); + auto var_tensor = convertBlob(layer.blobs(1)); + auto scale_tensor = convertBlob(layer.blobs(2)); + const float eps = opts.eps(); + + float scale_factor = *reinterpret_cast(scale_tensor.at(mir::Index{0})); + + // See https://github.com/BVLC/caffe/blob/master/src/caffe/layers/batch_norm_layer.cpp#L100 + // Y = (X - mean / scale_factor) / sqrt(var / scale_factor + epsilon) = + // = (X + C1) * C2 if (scale_factor != 0.0f) scale_factor = 1.0f / scale_factor; - // create bias argument from mean: - // multiply elements of mean by scaleFactor and get opposite numbers - // to subtract mean from input via add operation - auto mean_weights = convertBlob(layer.blobs(0)); - Tensor bias_data(mean_weights); - for (Index idx : ShapeRange(bias_data.getShape())) - bias_data.at(idx) *= -scale_factor; - auto mean = createOp("", mean_weights)->getOutput(0); - auto result = createOp(layer.name() + ".bias", convertCaffeToMIR(inputs[0]), mean) - ->getOutput(0); - - // create scale argument from variance: - // multiply elements of variance by scaleFactor and - // normalize biased input using scale operation - auto variance_weights = convertBlob(layer.blobs(1)); - Tensor scale_data(variance_weights); - for (Index idx : ShapeRange(scale_data.getShape())) - scale_data.at(idx) = 1.0f / std::sqrt(scale_data.at(idx) * scale_factor + eps); - auto variance = createOp("", variance_weights)->getOutput(0); - result = createOp(layer.name() + ".scale", result, variance)->getOutput(0); + // C1 = -mean / scale_factor + Tensor mean_accessor(mean_tensor); + for (const auto &idx : ShapeRange(mean_accessor.getShape())) + mean_accessor.at(idx) *= -scale_factor; + auto c1 = createOp("", mean_tensor)->getOutput(0); + + // C2 = 1 / sqrt(var / scale_factor + epsilon) + Tensor var_accessor(var_tensor); + for (const auto &idx : ShapeRange(var_accessor.getShape())) + var_accessor.at(idx) = 1.0f / std::sqrt(var_accessor.at(idx) * scale_factor + eps); + auto c2 = createOp("", var_tensor)->getOutput(0); + + // Y = (X + C1) * C2 + input = convertCaffeToMIR(input); + auto result = createOp("", input, c1)->getOutput(0); + result = createOp("", result, c2)->getOutput(0); return {convertMIRToCaffe(result)}; }