Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[tmva][sofie] Add Sin and Cos Operators to SOFIE #16809

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions tmva/sofie/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofie
TMVA/ROperator_Gemm.hxx
TMVA/ROperator_Relu.hxx
TMVA/ROperator_Tanh.hxx
TMVA/ROperator_Sin.hxx
TMVA/ROperator_Cos.hxx
TMVA/ROperator_LeakyRelu.hxx
TMVA/ROperator_Reshape.hxx
TMVA/ROperator_Selu.hxx
Expand Down
71 changes: 71 additions & 0 deletions tmva/sofie/inc/TMVA/ROperator_Cos.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef TMVA_SOFIE_ROPERATOR_Cos
#define TMVA_SOFIE_ROPERATOR_Cos

#include "TMVA/SOFIE_common.hxx"
#include "TMVA/ROperator.hxx"
#include "TMVA/RModel.hxx"

#include <sstream>

namespace TMVA{
namespace Experimental{
namespace SOFIE{

template <typename T>
class ROperator_Cos final : public ROperator
{

private:

std::string fNX;
std::string fNY;
std::vector<size_t> fShape;

public:
ROperator_Cos(){}
ROperator_Cos(std::string nameX, std::string nameY):
fNX(UTILITY::Clean_name(nameX)), fNY(UTILITY::Clean_name(nameY)){}

std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){
return input;
}

std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){
auto ret = input; //suggest copy to compiler
return ret;
}

void Initialize(RModel& model){
//input must be a graph input, or already initialized intermediate tensor
if (model.CheckIfTensorAlreadyExist(fNX) == false){
throw std::runtime_error("TMVA SOFIE Cos Op Input Tensor is not found in model");
}
fShape = model.GetTensorShape(fNX);
model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShape);

}


std::string Generate(std::string OpName){
OpName = "op_" + OpName;
if (fShape.empty()) {
throw std::runtime_error("TMVA SOFIE Cos operator called to Generate without being initialized first");
}
std::stringstream out;
size_t length = ConvertShapeToLength(fShape);
out << "\n//------ Cos\n";
out << SP << "for (int id = 0; id < " << length << " ; id++){\n";
out << SP << SP << "tensor_" << fNY << "[id] = std::cos(tensor_" << fNX << "[id]);\n";
out << SP << "}\n";
return out.str();
}

std::vector<std::string> GetStdLibs() { return { std::string("cmath") };}
};

}//SOFIE
}//Experimental
}//TMVA


#endif //TMVA_SOFIE_ROPERATOR_Cos
71 changes: 71 additions & 0 deletions tmva/sofie/inc/TMVA/ROperator_Sin.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#ifndef TMVA_SOFIE_ROPERATOR_Sin
#define TMVA_SOFIE_ROPERATOR_Sin

#include "TMVA/SOFIE_common.hxx"
#include "TMVA/ROperator.hxx"
#include "TMVA/RModel.hxx"

#include <sstream>

namespace TMVA{
namespace Experimental{
namespace SOFIE{

template <typename T>
class ROperator_Sin final : public ROperator
{

private:

std::string fNX;
std::string fNY;
std::vector<size_t> fShape;

public:
ROperator_Sin(){}
ROperator_Sin(std::string nameX, std::string nameY):
fNX(UTILITY::Clean_name(nameX)), fNY(UTILITY::Clean_name(nameY)){}

std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){
return input;
}

std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){
auto ret = input; //suggest copy to compiler
return ret;
}

void Initialize(RModel& model){
//input must be a graph input, or already initialized intermediate tensor
if (model.CheckIfTensorAlreadyExist(fNX) == false){
throw std::runtime_error("TMVA SOFIE Sin Op Input Tensor is not found in model");
}
fShape = model.GetTensorShape(fNX);
model.AddIntermediateTensor(fNY, model.GetTensorType(fNX), fShape);

}


std::string Generate(std::string OpName){
OpName = "op_" + OpName;
if (fShape.empty()) {
throw std::runtime_error("TMVA SOFIE Sin operator called to Generate without being initialized first");
}
std::stringstream out;
size_t length = ConvertShapeToLength(fShape);
out << "\n//------ Sin\n";
out << SP << "for (int id = 0; id < " << length << " ; id++){\n";
out << SP << SP << "tensor_" << fNY << "[id] = std::sin(tensor_" << fNX << "[id]);\n";
out << SP << "}\n";
return out.str();
}

std::vector<std::string> GetStdLibs() { return { std::string("cmath") };}
};

}//SOFIE
}//Experimental
}//TMVA


#endif //TMVA_SOFIE_ROPERATOR_Sin
55 changes: 55 additions & 0 deletions tmva/sofie/test/TestCustomModelsFromONNX.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
#include "Tanh_FromONNX.hxx"
#include "input_models/references/Tanh.ref.hxx"

#include "Sin_FromONNX.hxx"
#include "input_models/references/Sin.ref.hxx"

#include "Cos_FromONNX.hxx"
#include "input_models/references/Cos.ref.hxx"

#include "Erf_FromONNX.hxx"
#include "input_models/references/Erf.ref.hxx"

Expand Down Expand Up @@ -728,6 +734,55 @@ TEST(ONNX, Tanh)
}
}

TEST(ONNX, Sin)
{
constexpr float TOLERANCE = DEFAULT_TOLERANCE;

// Preparing the random input
std::vector<float> input({
-0.786738,-0.197796,-0.187787,0.142758,0.876096,-0.653239,0.145444,-1.107658,2.259171,-0.947054,-0.506689,1.801250
});

TMVA_SOFIE_Sin::Session s("Sin_FromONNX.dat");

std::vector<float> output = s.infer(input.data());

// Checking output size
EXPECT_EQ(output.size(), sizeof(Sin_ExpectedOutput::outputs) / sizeof(float));

float *correct = Sin_ExpectedOutput::outputs;

// Checking every output value, one by one
for (size_t i = 0; i < output.size(); ++i) {
EXPECT_LE(std::abs(output[i] - correct[i]), TOLERANCE);
}
}

TEST(ONNX, Cos)
{
constexpr float TOLERANCE = DEFAULT_TOLERANCE;

// Preparing the random input
std::vector<float> input({
1.152504,-1.459324,0.691594,0.347690,-1.307323,1.832516,-1.261772,0.014224,1.311477,1.147405,-0.567206,-0.530606
});

TMVA_SOFIE_Cos::Session s("Cos_FromONNX.dat");

std::vector<float> output = s.infer(input.data());

// Checking output size
EXPECT_EQ(output.size(), sizeof(Cos_ExpectedOutput::outputs) / sizeof(float));

float *correct = Cos_ExpectedOutput::outputs;

// Checking every output value, one by one
for (size_t i = 0; i < output.size(); ++i) {
EXPECT_LE(std::abs(output[i] - correct[i]), TOLERANCE);
}
}


TEST(ONNX, Erf)
{
constexpr float TOLERANCE = DEFAULT_TOLERANCE;
Expand Down
12 changes: 12 additions & 0 deletions tmva/sofie/test/input_models/Cos.onnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

 cos_example:S

inputoutput"CosCosGraphZ
input


b
output


B
12 changes: 12 additions & 0 deletions tmva/sofie/test/input_models/Sin.onnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

 onnx-example:S

inputoutput"Sinsin_testZ
input


b
output


B
4 changes: 4 additions & 0 deletions tmva/sofie/test/input_models/references/Cos.ref.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Cos_ExpectedOutput {
float outputs[] = {0.406200, 0.111242, 0.770231, 0.940162, 0.260436, -0.258742,
0.304129, 0.999899, 0.256423, 0.410855, 0.843406, 0.862500};
} // namespace Cos_ExpectedOutput
4 changes: 4 additions & 0 deletions tmva/sofie/test/input_models/references/Sin.ref.hxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
namespace Sin_ExpectedOutput {
float outputs[] = {-0.708054, -0.196509, -0.186685, 0.142274, 0.768246, -0.607762,
0.144932, -0.894655, 0.772279, -0.811698, -0.485285, 0.973563};
} // namespace Sin_ExpectedOutput
2 changes: 2 additions & 0 deletions tmva/sofie_parsers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ ROOT_STANDARD_LIBRARY_PACKAGE(ROOTTMVASofieParser
src/ParseSlice.cxx
src/ParseSoftmax.cxx
src/ParseTanh.cxx
src/ParseSin.cxx
src/ParseCos.cxx
src/ParseTranspose.cxx
src/ParseErf.cxx
src/ParseRange.cxx
Expand Down
39 changes: 39 additions & 0 deletions tmva/sofie_parsers/src/ParseCos.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "TMVA/RModelParser_ONNX.hxx"
#include "TMVA/ROperator_Cos.hxx"
#include "onnx_proto3.pb.h"

namespace TMVA {
namespace Experimental {
namespace SOFIE {

ParserFuncSignature ParseCos = [](RModelParser_ONNX &parser, const onnx::NodeProto &nodeproto) {
ETensorType input_type;

auto input_name = nodeproto.input(0);
if (parser.IsRegisteredTensorType(input_name)) {
input_type = parser.GetTensorType(input_name);
} else {
throw std::runtime_error("TMVA::SOFIE ONNX Parser Cos op has input tensor" + input_name +
" but its type is not yet registered");
}

std::unique_ptr<ROperator> op;
std::string output_name = nodeproto.output(0);

switch (input_type) {
case ETensorType::FLOAT: op.reset(new ROperator_Cos<float>(input_name, output_name)); break;
default:
throw std::runtime_error("TMVA::SOFIE - Unsupported - Operator Cos does not yet support input type " +
std::to_string(static_cast<int>(input_type)));
}

if (!parser.IsRegisteredTensorType(output_name)) {
parser.RegisterTensorType(output_name, input_type);
}

return op;
};

} // namespace SOFIE
} // namespace Experimental
} // namespace TMVA
39 changes: 39 additions & 0 deletions tmva/sofie_parsers/src/ParseSin.cxx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "TMVA/RModelParser_ONNX.hxx"
#include "TMVA/ROperator_Sin.hxx"
#include "onnx_proto3.pb.h"

namespace TMVA {
namespace Experimental {
namespace SOFIE {

ParserFuncSignature ParseSin = [](RModelParser_ONNX &parser, const onnx::NodeProto &nodeproto) {
ETensorType input_type;

auto input_name = nodeproto.input(0);
if (parser.IsRegisteredTensorType(input_name)) {
input_type = parser.GetTensorType(input_name);
} else {
throw std::runtime_error("TMVA::SOFIE ONNX Parser Sin op has input tensor" + input_name +
" but its type is not yet registered");
}

std::unique_ptr<ROperator> op;
std::string output_name = nodeproto.output(0);

switch (input_type) {
case ETensorType::FLOAT: op.reset(new ROperator_Sin<float>(input_name, output_name)); break;
default:
throw std::runtime_error("TMVA::SOFIE - Unsupported - Operator Sin does not yet support input type " +
std::to_string(static_cast<int>(input_type)));
}

if (!parser.IsRegisteredTensorType(output_name)) {
parser.RegisterTensorType(output_name, input_type);
}

return op;
};

} // namespace SOFIE
} // namespace Experimental
} // namespace TMVA
4 changes: 4 additions & 0 deletions tmva/sofie_parsers/src/RModelParser_ONNX.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ extern ParserFuncSignature ParseConstant;
extern ParserFuncSignature ParseTranspose;
extern ParserFuncSignature ParseRelu;
extern ParserFuncSignature ParseTanh;
extern ParserFuncSignature ParseSin;
extern ParserFuncSignature ParseCos;
extern ParserFuncSignature ParseConv;
extern ParserFuncSignature ParseConvTranspose;
extern ParserFuncSignature ParseLeakyRelu;
Expand Down Expand Up @@ -200,6 +202,8 @@ RModelParser_ONNX::RModelParser_ONNX() noexcept : fOperatorsMapImpl(std::make_un
RegisterOperator("Slice", ParseSlice);
RegisterOperator("Softmax", ParseSoftmax);
RegisterOperator("Tanh", ParseTanh);
RegisterOperator("Sin", ParseSin);
RegisterOperator("Cos", ParseCos);
RegisterOperator("Transpose", ParseTranspose);
RegisterOperator("MatMul", ParseMatMul);
RegisterOperator("LayerNormalization", ParseLayerNormalization);
Expand Down
Loading