Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMVA_SOFIE_GNN_Application.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_ml
3/// \notebook -nodraw
4/// Macro evaluating a GNN model which was generated with the Parser macro
5/// TMVA_SOFIE_GNN_Parser.py
6///
7/// \macro_code
8///
9/// \author
10
11// need to add include path to find generated model file
12#ifdef __CLING__
14#endif
15
16#include "encoder.hxx"
17#include "core.hxx"
18#include "decoder.hxx"
19#include "output_transform.hxx"
20
21#include "TRandom3.h"
22#include "TH1.h"
23#include "TCanvas.h"
24#include "TFile.h"
25#include "TTree.h"
26#include "TSystem.h"
27#include "TStopwatch.h"
28#include "TMath.h"
29#include "ROOT/RDataFrame.hxx"
30
31#include <vector>
32
33const int num_max_nodes = 100;
34const int num_max_edges = 300;
35const int NODE_FEATURE_SIZE = 4;
36const int EDGE_FEATURE_SIZE = 4;
37const int GLOBAL_FEATURE_SIZE = 1;
38const int LATENT_SIZE = 100;
39
40double check_mem(std::string s = ""){
42 printf("%s - ",s.c_str());
44 printf(" Rmem = %8.3f MB, Vmem = %8.f3 MB \n",
45 p.fMemResident /1024., /// convert memory from kB to MB
46 p.fMemVirtual /1024.
47 );
48 return p.fMemResident / 1024.;
49}
50
51// graph data for one event
52struct GNN_Data {
53 size_t num_nodes = 0;
54 size_t num_edges = 0;
55 std::vector<float> node_data; // { num_nodes, node features }
56 std::vector<float> edge_data; // { num_edges, edge features }
57 std::vector<float> global_data; // { 1, global features }
58 std::vector<int64_t> receivers; // { num_edges }
59 std::vector<int64_t> senders; // { num_edges }
60};
61
62// concatenate the feature dimensions of two row-major {rows, f1} and {rows, f2} tensors
63std::vector<float> ConcatenateFeatures(const std::vector<float> & a, const std::vector<float> & b, size_t rows)
64{
65 size_t fa = a.size() / rows, fb = b.size() / rows;
66 std::vector<float> out(rows * (fa + fb));
67 for (size_t i = 0; i < rows; i++) {
68 std::copy(a.begin() + i * fa, a.begin() + (i + 1) * fa, out.begin() + i * (fa + fb));
69 std::copy(b.begin() + i * fb, b.begin() + (i + 1) * fb, out.begin() + i * (fa + fb) + fa);
70 }
71 return out;
72}
73
74struct SOFIE_GNN {
75 // the sessions are created for the maximum number of nodes/edges
76 TMVA_SOFIE_encoder::Session encoder{"encoder.dat", num_max_edges, num_max_nodes};
77 TMVA_SOFIE_core::Session core{"core.dat", num_max_edges, num_max_nodes};
78 TMVA_SOFIE_decoder::Session decoder{"decoder.dat", num_max_edges, num_max_nodes};
79 TMVA_SOFIE_output_transform::Session output_transform{"output_transform.dat", num_max_edges, num_max_nodes};
80
81 // each session returns the {node, edge, global} output tensors
82 std::vector<std::vector<float>> Infer(const GNN_Data & d, int nsteps) {
83 auto latent = encoder.infer(d.num_nodes, d.node_data.data(), d.num_edges, d.edge_data.data(),
84 d.global_data.data());
85 auto latent0 = latent;
86 std::vector<std::vector<float>> output;
87 for (int i = 0; i < nsteps; i++) {
88 auto node_input = ConcatenateFeatures(latent0[0], latent[0], d.num_nodes);
89 auto edge_input = ConcatenateFeatures(latent0[1], latent[1], d.num_edges);
91 latent = core.infer(d.num_nodes, node_input.data(), d.num_edges, edge_input.data(),
92 global_input.data(), d.receivers.data(), d.senders.data());
93 auto decoded = decoder.infer(d.num_nodes, latent[0].data(), d.num_edges, latent[1].data(),
94 latent[2].data());
95 output = output_transform.infer(d.num_nodes, decoded[0].data(), d.num_edges, decoded[1].data(),
96 decoded[2].data());
97 }
98 return output;
99 }
100};
101
102std::vector<GNN_Data> ReadData(std::string treename, std::string filename) {
109 int nevts = ndata.GetPtr()->size();
110 std::vector<GNN_Data> dataSet;
111 dataSet.reserve(nevts);
112 for (int i = 0; i < nevts; i++) {
113 GNN_Data gd;
114 auto & n = (*(ndata.GetPtr()))[i];
115 auto & e = (*(edata.GetPtr()))[i];
116 auto & g = (*(gdata.GetPtr()))[i];
117 auto & r = (*(rdata.GetPtr()))[i];
118 auto & s = (*(sdata.GetPtr()))[i];
119 gd.num_nodes = n.size()/NODE_FEATURE_SIZE;
120 gd.num_edges = e.size()/EDGE_FEATURE_SIZE;
121 gd.node_data.assign(n.begin(), n.end());
122 gd.edge_data.assign(e.begin(), e.end());
123 gd.global_data.assign(g.begin(), g.end());
124 gd.receivers.assign(r.begin(), r.end());
125 gd.senders.assign(s.begin(), s.end());
126 dataSet.emplace_back(std::move(gd));
127 }
128 return dataSet;
129}
130
131
132void TMVA_SOFIE_GNN_Application (bool verbose = false)
133{
134 check_mem("Initial memory");
136 check_mem("After creating GNN");
137
138 const int nproc_steps = 5;
139
140 std::cout << "reading data\n";
141 auto inputData = ReadData("gdata","graph_data.root");
142 int nevts = inputData.size();
143
144 auto h1 = new TH1D("h1_sofie","SOFIE Node data",40,1,0);
145 auto h2 = new TH1D("h2_sofie","SOFIE Edge data",40,1,0);
146 auto h3 = new TH1D("h3_sofie","SOFIE Global data",40,1,0);
147 std::cout << "doing inference...\n";
148
149 check_mem("Before evaluating");
150 TStopwatch w; w.Start();
151 for (int i = 0; i < nevts; i++) {
152 auto result = gnn.Infer(inputData[i], nproc_steps);
153 // compute resulting means and plot them
154 h1->Fill(TMath::Mean(result[0].begin(), result[0].end()));
155 h2->Fill(TMath::Mean(result[1].begin(), result[1].end()));
156 h3->Fill(TMath::Mean(result[2].begin(), result[2].end()));
157 }
158 w.Stop();
159 w.Print();
160 check_mem("End evaluation");
161 auto c1 = new TCanvas("c1","SOFIE Results");
162 c1->Divide(1,3);
163 c1->cd(1); h1->Draw();
164 c1->cd(2); h2->Draw();
165 c1->cd(3); h3->Draw();
166
167 // compare with the reference PyTorch result made by the Parser tutorial
168 auto c2 = new TCanvas("c2","Reference Results");
169 auto file = TFile::Open("graph_data.root");
170 auto o1 = file->Get<TH1D>("h1");
171 auto o2 = file->Get<TH1D>("h2");
172 auto o3 = file->Get<TH1D>("h3");
173 c2->Divide(1,3);
174 c2->cd(1); o1->Draw();
175 c2->cd(2); o2->Draw();
176 c2->cd(3); o3->Draw();
177
178 // check the mean of the global-data output distribution against the reference
179 if (verbose)
180 std::cout << "SOFIE global mean " << h3->GetMean() << " reference " << o3->GetMean() << std::endl;
181 if (std::abs(h3->GetMean() - o3->GetMean()) > 5e-4)
182 std::cerr << "Error in comparing SOFIE and reference results" << std::endl;
183}
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define g(i)
Definition RSha256.hxx:105
#define a(i)
Definition RSha256.hxx:99
#define e(i)
Definition RSha256.hxx:103
#define R__ADD_INCLUDE_PATH(PATH)
Definition Rtypes.h:474
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
R__EXTERN TSystem * gSystem
Definition TSystem.h:582
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...
const_iterator begin() const
const_iterator end() const
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1509
The Canvas class.
Definition TCanvas.h:23
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:3801
1-D histogram with a double per channel (see TH1 documentation)
Definition TH1.h:926
virtual Int_t Fill(Double_t x)
Increment bin with abscissa X by 1.
Definition TH1.cxx:3489
void Draw(Option_t *option="") override
Draw this histogram with options.
Definition TH1.cxx:3193
Stopwatch class.
Definition TStopwatch.h:28
virtual int GetProcInfo(ProcInfo_t *info) const
Returns cpu and memory used by this process into the ProcInfo_t structure.
Definition TSystem.cxx:2509
return c1
Definition legend1.C:41
const Int_t n
Definition legend1.C:16
TH1F * h1
Definition legend1.C:5
return c2
Definition legend2.C:14
Double_t Mean(Long64_t n, const T *a, const Double_t *w=nullptr)
Returns the weighted mean of an array a with length n.
Definition TMath.h:1182