Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMVA_SOFIE_GNN.py
Go to the documentation of this file.
1import ROOT
2
3import numpy as np
4import graph_nets as gn
5from graph_nets import utils_tf
6import sonnet as snt
7import time
8
9# defining graph properties
10num_nodes=5
11num_edges=20
12snd = np.array([1,2,3,4,2,3,4,3,4,4,0,0,0,0,1,1,1,2,2,3], dtype='int32')
13rec = np.array([0,0,0,0,1,1,1,2,2,3,1,2,3,4,2,3,4,3,4,4], dtype='int32')
14node_size=4
15edge_size=4
16global_size=1
17LATENT_SIZE = 100
18NUM_LAYERS = 4
19processing_steps = 5
20
21# method for returning dictionary of graph data
22def get_graph_data_dict(num_nodes, num_edges, NODE_FEATURE_SIZE=2, EDGE_FEATURE_SIZE=2, GLOBAL_FEATURE_SIZE=1):
23 return {
24 "globals": 10*np.random.rand(GLOBAL_FEATURE_SIZE).astype(np.float32)-5.,
25 "nodes": 10*np.random.rand(num_nodes, NODE_FEATURE_SIZE).astype(np.float32)-5.,
26 "edges": 10*np.random.rand(num_edges, EDGE_FEATURE_SIZE).astype(np.float32)-5.,
27 "senders": snd,
28 "receivers": rec
29 }
30
31# method to instantiate mlp model to be added in GNN
33 return snt.Sequential([
34 snt.nets.MLP([LATENT_SIZE]*NUM_LAYERS, activate_final=True),
35 snt.LayerNorm(axis=-1, create_offset=True, create_scale=True)
36 ])
37
38# defining GraphIndependent class with MLP edge, node, and global models.
39class MLPGraphIndependent(snt.Module):
40 def __init__(self, name="MLPGraphIndependent"):
41 super(MLPGraphIndependent, self).__init__(name=name)
42 self._network = gn.modules.GraphIndependent(
43 edge_model_fn = lambda: snt.nets.MLP([LATENT_SIZE]*NUM_LAYERS, activate_final=True),
44 node_model_fn = lambda: snt.nets.MLP([LATENT_SIZE]*NUM_LAYERS, activate_final=True),
45 global_model_fn = lambda: snt.nets.MLP([LATENT_SIZE]*NUM_LAYERS, activate_final=True))
46
47 def __call__(self, inputs):
48 return self._network(inputs)
49
50# defining Graph network class with MLP edge, node, and global models.
51class MLPGraphNetwork(snt.Module):
52 def __init__(self, name="MLPGraphNetwork"):
53 super(MLPGraphNetwork, self).__init__(name=name)
54 self._network = gn.modules.GraphNetwork(
55 edge_model_fn=make_mlp_model,
56 node_model_fn=make_mlp_model,
57 global_model_fn=make_mlp_model)
58
59 def __call__(self, inputs):
60 return self._network(inputs)
61
62# defining a Encode-Process-Decode module for LHCb toy model
63class EncodeProcessDecode(snt.Module):
64
65 def __init__(self,
66 name="EncodeProcessDecode"):
67 super(EncodeProcessDecode, self).__init__(name=name)
72
73 def __call__(self, input_op, num_processing_steps):
74 latent = self._encoder(input_op)
75 latent0 = latent
76 output_ops = []
77 for _ in range(num_processing_steps):
78 core_input = utils_tf.concat([latent0, latent], axis=1)
79 latent = self._core(core_input)
80 decoded_op = self._decoder(latent)
81 output_ops.append(self._output_transform(decoded_op))
82 return output_ops
83
84
85# Instantiating EncodeProcessDecode Model
87
88# Initializing randomized input data
89GraphData = get_graph_data_dict(num_nodes,num_edges, node_size, edge_size, global_size)
90
91#input_graphs is a tuple representing the initial data
92input_graph_data = utils_tf.data_dicts_to_graphs_tuple([GraphData])
93
94# Initializing randomized input data for core
95# note that the core network has as input a double number of features
96CoreGraphData = get_graph_data_dict(num_nodes, num_edges, 2*LATENT_SIZE, 2*LATENT_SIZE, 2*LATENT_SIZE)
97input_core_graph_data = utils_tf.data_dicts_to_graphs_tuple([CoreGraphData])
98
99#initialize graph data for decoder (input is LATENT_SIZE)
100DecodeGraphData = get_graph_data_dict(num_nodes,num_edges, LATENT_SIZE, LATENT_SIZE, LATENT_SIZE)
101
102# Make prediction of GNN
103output_gn = ep_model(input_graph_data, processing_steps)
104#print("---> Input:\n",input_graph_data)
105#print("\n\n------> Input core data:\n",input_core_graph_data)
106#print("\n\n---> Output:\n",output_gn)
107
108# Make SOFIE Model
109encoder = ROOT.TMVA.Experimental.SOFIE.RModel_GraphIndependent.ParseFromMemory(ep_model._encoder._network, GraphData, filename = "gnn_encoder")
110encoder.Generate()
111encoder.OutputGenerated()
112
113core = ROOT.TMVA.Experimental.SOFIE.RModel_GNN.ParseFromMemory(ep_model._core._network, CoreGraphData, filename = "gnn_core")
114core.Generate()
115core.OutputGenerated()
116
117decoder = ROOT.TMVA.Experimental.SOFIE.RModel_GraphIndependent.ParseFromMemory(ep_model._decoder._network, DecodeGraphData, filename = "gnn_decoder")
118decoder.Generate()
119decoder.OutputGenerated()
120
121output_transform = ROOT.TMVA.Experimental.SOFIE.RModel_GraphIndependent.ParseFromMemory(ep_model._output_transform._network, DecodeGraphData, filename = "gnn_output_transform")
122output_transform.Generate()
123output_transform.OutputGenerated()
124
125# Compile now the generated C++ code from SOFIE
126gen_code = '''#pragma cling optimize(2)
127#include "gnn_encoder.hxx"
128#include "gnn_core.hxx"
129#include "gnn_decoder.hxx"
130#include "gnn_output_transform.hxx"'''
131ROOT.gInterpreter.Declare(gen_code)
132
133#helper function to print SOFIE GNN data structure
134def PrintSofie(output, printShape = False):
135 n = np.asarray(output.node_data)
136 e = np.asarray(output.edge_data)
137 g = np.asarray(output.global_data)
138 if (printShape) :
139 print("SOFIE data ... shapes",n.shape,e.shape,g.shape)
140 print(" node data", n.reshape(n.size,))
141 print(" edge data", e.reshape(e.size,))
142 print(" global data",g.reshape(g.size,))
143
144def CopyData(input_data) :
145 output_data = ROOT.TMVA.Experimental.SOFIE.Copy(input_data)
146 return output_data
147
148# Build SOFIE GNN Model and run inference
150 def __init__(self):
151 self.encoder_session = ROOT.TMVA_SOFIE_gnn_encoder.Session()
152 self.core_session = ROOT.TMVA_SOFIE_gnn_core.Session()
153 self.decoder_session = ROOT.TMVA_SOFIE_gnn_decoder.Session()
154 self.output_transform_session = ROOT.TMVA_SOFIE_gnn_output_transform.Session()
155
156 def infer(self, graphData):
157 # copy the input data
158 input_data = CopyData(graphData)
159
160 # running inference on sofie
161 self.encoder_session.infer(input_data)
162 latent0 = CopyData(input_data)
163 latent = input_data
164 output_ops = []
165 for _ in range(processing_steps):
166 core_input = ROOT.TMVA.Experimental.SOFIE.Concatenate(latent0, latent, axis=1)
167 self.core_session.infer(core_input)
168 latent = CopyData(core_input)
169 self.decoder_session.infer(core_input)
170 self.output_transform_session.infer(core_input)
171 output = CopyData(core_input)
172 output_ops.append(output)
173
174 return output_ops
175
176# Test both GNN on some simulated events
178 data = get_graph_data_dict(num_nodes,num_edges, node_size, edge_size, global_size)
179 return data
180
181numevts = 40
182dataSet = []
183for i in range(0,numevts):
185 dataSet.append(data)
186
187# Run graph_nets model
188# First we convert input data to the required input format
189gnetData = []
190for i in range(0,numevts):
191 graphData = dataSet[i]
192 gnet_data_i = utils_tf.data_dicts_to_graphs_tuple([graphData])
193 gnetData.append(gnet_data_i)
194
195# Function to run the graph net
196def RunGNet(inputGraphData) :
197 output_gn = ep_model(inputGraphData, processing_steps)
198 return output_gn
199
200start = time.time()
201hG = ROOT.TH1D("hG","Result from graphnet",20,1,0)
202for i in range(0,numevts):
203 out = RunGNet(gnetData[i])
204 g = out[1].globals.numpy()
205 hG.Fill(np.mean(g))
206
207end = time.time()
208print("elapsed time for ",numevts,"events = ",end-start)
209
210# running SOFIE-GNN
211sofieData = []
212for i in range(0,numevts):
213 graphData = dataSet[i]
214 input_data = ROOT.TMVA.Experimental.SOFIE.GNN_Data()
215 input_data.node_data = ROOT.TMVA.Experimental.AsRTensor(graphData['nodes'])
216 input_data.edge_data = ROOT.TMVA.Experimental.AsRTensor(graphData['edges'])
217 input_data.global_data = ROOT.TMVA.Experimental.AsRTensor(graphData['globals'])
218 input_data.edge_index = ROOT.TMVA.Experimental.AsRTensor(np.stack((graphData['receivers'],graphData['senders'])))
219 sofieData.append(input_data)
220
221
222endSC = time.time()
223print("time to convert data to SOFIE format",endSC-end)
224
225hS = ROOT.TH1D("hS","Result from SOFIE",20,1,0)
226start0 = time.time()
227gnn = SofieGNN()
228start = time.time()
229print("time to create SOFIE GNN class", start-start0)
230for i in range(0,numevts):
231 #print("inference event....",i)
232 out = gnn.infer(sofieData[i])
233 g = np.asarray(out[1].global_data)
234 hS.Fill(np.mean(g))
235
236end = time.time()
237print("elapsed time for ",numevts,"events = ",end-start)
238
239c0 = ROOT.TCanvas()
240c0.Divide(1,2)
241c1 = c0.cd(1)
242c1.Divide(2,1)
243c1.cd(1)
244hG.Draw()
245c1.cd(2)
246hS.Draw()
247
248hDe = ROOT.TH1D("hDe","Difference for edge data",40,1,0)
249hDn = ROOT.TH1D("hDn","Difference for node data",40,1,0)
250hDg = ROOT.TH1D("hDg","Difference for global data",40,1,0)
251#compute differences between SOFIE and GNN
252for i in range(0,numevts):
253 outSofie = gnn.infer(sofieData[i])
254 outGnet = RunGNet(gnetData[i])
255 edgesG = outGnet[1].edges.numpy()
256 edgesS = np.asarray(outSofie[1].edge_data)
257 if (i == 0) : print(edgesG.shape)
258 for j in range(0,edgesG.shape[0]) :
259 for k in range(0,edgesG.shape[1]) :
260 hDe.Fill(edgesG[j,k]-edgesS[j,k])
261
262 nodesG = outGnet[1].nodes.numpy()
263 nodesS = np.asarray(outSofie[1].node_data)
264 for j in range(0,nodesG.shape[0]) :
265 for k in range(0,nodesG.shape[1]) :
266 hDn.Fill(nodesG[j,k]-nodesS[j,k])
267
268 globG = outGnet[1].globals.numpy()
269 globS = np.asarray(outSofie[1].global_data)
270 for j in range(0,globG.shape[1]) :
271 hDg.Fill(globG[0,j]-globS[j])
272
273
274c2 = c0.cd(2)
275c2.Divide(3,1)
276c2.cd(1)
277hDe.Draw()
278c2.cd(2)
279hDn.Draw()
280c2.cd(3)
281hDg.Draw()
282
283c0.Draw()
284
285
__call__(self, input_op, num_processing_steps)
__init__(self, name="EncodeProcessDecode")
__init__(self, name="MLPGraphIndependent")
__init__(self, name="MLPGraphNetwork")
CopyData(input_data)
get_graph_data_dict(num_nodes, num_edges, NODE_FEATURE_SIZE=2, EDGE_FEATURE_SIZE=2, GLOBAL_FEATURE_SIZE=1)
RunGNet(inputGraphData)
PrintSofie(output, printShape=False)