Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_InstanceNormalization.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_INSTANCENORMALIZATION
2#define TMVA_SOFIE_ROPERATOR_INSTANCENORMALIZATION
3
4#include "TMVA/ROperator.hxx"
5#include "TMVA/RModel.hxx"
7
8#include <sstream>
9#include <stdexcept>
10
11namespace TMVA {
12namespace Experimental {
13namespace SOFIE {
14
15/*! \class ROperator_InstanceNormalization
16 \brief Implementation of the ONNX InstanceNormalization operator.
17
18 The input X has shape (N, C, D1, ..., Dn). For every sample n and channel c,
19 the elements over the spatial dimensions D1, ..., Dn are normalized to zero
20 mean and unit variance, and then scaled and shifted with the per-channel
21 scale and B tensors, which both have shape (C):
22
23 Y[n, c, ...] = scale[c] * (X[n, c, ...] - mean[n, c]) / sqrt(var[n, c] + epsilon) + B[c]
24*/
25template <typename T>
27private:
28 float fEpsilon;
29 std::string fNInput;
30 std::string fNScale;
31 std::string fNBias;
32 std::string fNOutput;
33 std::vector<size_t> fShape;
34 std::string fType;
35
36public:
38
39 ROperator_InstanceNormalization(float epsilon, std::string nameInput, std::string nameScale, std::string nameBias,
40 std::string nameOutput)
41 : fEpsilon(epsilon),
42 fNInput(UTILITY::Clean_name(nameInput)),
43 fNScale(UTILITY::Clean_name(nameScale)),
44 fNBias(UTILITY::Clean_name(nameBias)),
45 fNOutput(UTILITY::Clean_name(nameOutput))
46 {
49 }
50
51 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> inputShapes) override
52 {
53 return {inputShapes[0]};
54 }
55
56 void Initialize(RModel &model) override
57 {
58 for (const std::string &name : {fNInput, fNScale, fNBias}) {
59 if (!model.CheckIfTensorAlreadyExist(name)) {
60 throw std::runtime_error("TMVA::SOFIE - InstanceNormalization - Tensor " + name + " not found.");
61 }
62 }
63
65 if (fShape.size() < 3) {
66 throw std::runtime_error("TMVA::SOFIE - InstanceNormalization - Input tensor " + fNInput + " has rank " +
67 std::to_string(fShape.size()) + " but at least rank 3 (N, C, D1, ...) is required.");
68 }
69
70 // scale and B are 1D tensors of length C
71 const size_t channels = fShape[1];
72 for (const std::string &name : {fNScale, fNBias}) {
73 auto shape = model.GetTensorShape(name);
74 if (shape.size() != 1 || shape[0] != channels) {
75 throw std::runtime_error("TMVA::SOFIE - InstanceNormalization - Tensor " + name + " has invalid shape " +
76 ConvertShapeToString(shape) + ", expected " +
77 ConvertShapeToString(std::vector<size_t>{channels}) + ".");
78 }
79 }
80
83 }
84
85 std::string Generate(std::string) override
86 {
87 if (fShape.empty()) {
88 throw std::runtime_error("TMVA::SOFIE - InstanceNormalization called to generate without being initialized.");
89 }
90
91 const size_t batchSize = fShape[0];
92 const size_t channels = fShape[1];
93 size_t spatialSize = 1;
94 for (size_t i = 2; i < fShape.size(); ++i)
95 spatialSize *= fShape[i];
96
97 std::stringstream out;
98 out << "\n" << SP << "//---- InstanceNormalization " << fNOutput << "\n";
99 out << SP << "for (size_t n = 0; n < " << batchSize << "; n++) {\n";
100 out << SP << SP << "for (size_t c = 0; c < " << channels << "; c++) {\n";
101 out << SP << SP << SP << "const size_t offset = n * " << channels * spatialSize << " + c * " << spatialSize
102 << ";\n";
103
104 // Compute the mean over the spatial dimensions
105 out << SP << SP << SP << fType << " mean = 0.;\n";
106 out << SP << SP << SP << "for (size_t i = 0; i < " << spatialSize << "; i++) {\n";
107 out << SP << SP << SP << SP << "mean += tensor_" << fNInput << "[offset + i];\n";
108 out << SP << SP << SP << "}\n";
109 out << SP << SP << SP << "mean /= " << fType << "(" << spatialSize << ");\n";
110
111 // Compute the inverse standard deviation from the deviations around the mean
112 out << SP << SP << SP << fType << " sum = 0.;\n";
113 out << SP << SP << SP << "for (size_t i = 0; i < " << spatialSize << "; i++) {\n";
114 out << SP << SP << SP << SP << fType << " tmp = tensor_" << fNInput << "[offset + i] - mean;\n";
115 out << SP << SP << SP << SP << "sum += tmp * tmp;\n";
116 out << SP << SP << SP << "}\n";
117 out << SP << SP << SP << fType << " invStdDev = 1 / std::sqrt(sum / " << fType << "(" << spatialSize << ") + "
118 << std::to_string(fEpsilon) << ");\n";
119
120 // Y = scale o invStdDev (X - mean) + B
121 out << SP << SP << SP << fType << " scale = tensor_" << fNScale << "[c];\n";
122 out << SP << SP << SP << fType << " bias = tensor_" << fNBias << "[c];\n";
123 out << SP << SP << SP << "for (size_t i = 0; i < " << spatialSize << "; i++) {\n";
124 out << SP << SP << SP << SP << "tensor_" << fNOutput << "[offset + i] = scale * (tensor_" << fNInput
125 << "[offset + i] - mean) * invStdDev + bias;\n";
126 out << SP << SP << SP << "}\n";
127
128 out << SP << SP << "}\n";
129 out << SP << "}\n";
130 return out.str();
131 }
132};
133
134} // namespace SOFIE
135} // namespace Experimental
136} // namespace TMVA
137#endif
#define e(i)
Definition RSha256.hxx:103
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
char name[80]
Definition TGX11.cxx:148
std::vector< size_t > GetTensorShape(const std::string &name) const
Definition RModel.cxx:64
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:311
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:157
ETensorType GetTensorType(std::string name) const
Definition RModel.cxx:125
Implementation of the ONNX InstanceNormalization operator.
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > inputShapes) override
ROperator_InstanceNormalization(float epsilon, std::string nameInput, std::string nameScale, std::string nameBias, std::string nameOutput)
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:50
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:45
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:51
std::string ConvertTypeToString(ETensorType type)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations