1#ifndef TMVA_SOFIE_ROPERATOR_INSTANCENORMALIZATION
2#define TMVA_SOFIE_ROPERATOR_INSTANCENORMALIZATION
12namespace Experimental {
40 std::string nameOutput)
42 fNInput(UTILITY::Clean_name(nameInput)),
43 fNScale(UTILITY::Clean_name(nameScale)),
44 fNBias(UTILITY::Clean_name(nameBias)),
45 fNOutput(UTILITY::Clean_name(nameOutput))
54 if (!model.CheckIfTensorAlreadyExist(
name)) {
55 throw std::runtime_error(
"TMVA::SOFIE - InstanceNormalization - Tensor " +
name +
" not found.");
61 throw std::runtime_error(
"TMVA::SOFIE - InstanceNormalization - Input tensor " +
fNInput +
" has rank " +
62 std::to_string(
fShape.size()) +
" but at least rank 3 (N, C, D1, ...) is required.");
66 const size_t channels =
fShape[1];
68 auto shape = model.GetTensorShape(
name);
69 if (shape.size() != 1 || shape[0] != channels) {
70 throw std::runtime_error(
"TMVA::SOFIE - InstanceNormalization - Tensor " +
name +
" has invalid shape " +
83 throw std::runtime_error(
"TMVA::SOFIE - InstanceNormalization called to generate without being initialized.");
86 const size_t batchSize =
fShape[0];
87 const size_t channels =
fShape[1];
88 size_t spatialSize = 1;
89 for (
size_t i = 2; i <
fShape.size(); ++i)
92 std::stringstream out;
93 out <<
"\n" <<
SP <<
"//---- InstanceNormalization " <<
fNOutput <<
"\n";
94 out <<
SP <<
"for (size_t n = 0; n < " << batchSize <<
"; n++) {\n";
95 out <<
SP <<
SP <<
"for (size_t c = 0; c < " << channels <<
"; c++) {\n";
96 out <<
SP <<
SP <<
SP <<
"const size_t offset = n * " << channels * spatialSize <<
" + c * " << spatialSize
101 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " << spatialSize <<
"; i++) {\n";
102 out <<
SP <<
SP <<
SP <<
SP <<
"mean += tensor_" <<
fNInput <<
"[offset + i];\n";
103 out <<
SP <<
SP <<
SP <<
"}\n";
104 out <<
SP <<
SP <<
SP <<
"mean /= " <<
fType <<
"(" << spatialSize <<
");\n";
108 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " << spatialSize <<
"; i++) {\n";
109 out <<
SP <<
SP <<
SP <<
SP <<
fType <<
" tmp = tensor_" <<
fNInput <<
"[offset + i] - mean;\n";
110 out <<
SP <<
SP <<
SP <<
SP <<
"sum += tmp * tmp;\n";
111 out <<
SP <<
SP <<
SP <<
"}\n";
112 out <<
SP <<
SP <<
SP <<
fType <<
" invStdDev = 1 / std::sqrt(sum / " <<
fType <<
"(" << spatialSize <<
") + "
113 << std::to_string(
fEpsilon) <<
");\n";
118 out <<
SP <<
SP <<
SP <<
"for (size_t i = 0; i < " << spatialSize <<
"; i++) {\n";
120 <<
"[offset + i] - mean) * invStdDev + bias;\n";
121 out <<
SP <<
SP <<
SP <<
"}\n";
123 out <<
SP <<
SP <<
"}\n";
Implementation of the ONNX InstanceNormalization operator.
void Initialize(RModel &model) override
ROperator_InstanceNormalization()
ROperator_InstanceNormalization(float epsilon, std::string nameInput, std::string nameScale, std::string nameBias, std::string nameOutput)
std::string Generate(std::string) override
std::vector< size_t > fShape
std::vector< std::string_view > fInputTensorNames
const std::string SP
space used to correctly indent the generated C++ code
std::vector< std::string_view > fOutputTensorNames
std::string ConvertTypeToString(ETensorType type)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations