43modelNames = sys.argv[2:]
46@contextlib.contextmanager
47def expect_warning(category, message):
48 # Silence a known third-party warning and raise if it stops firing.
50 # Notifies us to drop the workaround once the upstream library is fixed.
51 with warnings.catch_warnings(record=True) as caught:
52 warnings.simplefilter("always")
56 if issubclass(w.category, category) and message in str(w.message):
59 warnings.warn_explicit(w.message, w.category, w.filename, w.lineno)
62 f"Expected {category.__name__} containing {message!r} was not "
63 "emitted. This tutorial's workaround can probably be removed."
67def CreateModel(nlayers=4, nunits=64):
70 for i in range(nlayers):
71 layers += [nn.Linear(ninputs, nunits), nn.ReLU()]
73 layers += [nn.Linear(ninputs, 1), nn.Sigmoid()]
74 model = nn.Sequential(*layers)
79def TrainModel(model, x, y, epochs=5, batch_size=50):
80 x = torch.from_numpy(x)
81 y = torch.from_numpy(y)
82 criterion = nn.BCELoss()
83 optimizer = torch.optim.Adam(model.parameters())
84 nbatches = x.shape[0] // batch_size
85 for epoch in range(epochs):
86 perm = torch.randperm(x.shape[0])
88 for i in range(nbatches):
89 idx = perm[i * batch_size : (i + 1) * batch_size]
91 loss = criterion(model(x[idx]), y[idx])
94 running_loss += loss.item()
95 print(f"Epoch {epoch + 1}/{epochs} - average loss: {running_loss / nbatches:.4f}")
98def ExportModel(model, modelName):
99 # need to evaluate the model before exporting to ONNX
100 # and to provide a dummy input tensor to set the input model shape
101 # (the batch size is fixed to 1 for the SOFIE inference)
104 modelFile = modelName + ".onnx"
105 dummy_x = torch.randn(1, 7)
108 # check for torch.onnx.export parameters
109 def filtered_kwargs(func, **candidate_kwargs):
110 sig = inspect.signature(func)
111 return {k: v for k, v in candidate_kwargs.items() if k in sig.parameters}
113 kwargs = filtered_kwargs(
115 input_names=["input"],
116 output_names=["output"],
117 external_data=False, # may not exist
118 dynamo=True, # may not exist
120 print("calling torch.onnx.export with parameters", kwargs)
123 # torch.onnx.export (dynamo path) pickles its export program through
124 # copyreg, which still references the deprecated LeafSpec. The warning
125 # is emitted from inside PyTorch and cannot be avoided from user code.
126 with expect_warning(FutureWarning, "isinstance(treespec, LeafSpec)"):
127 torch.onnx.export(model, dummy_x, modelFile, **kwargs)
128 print("model exported to ONNX as", modelFile)
130 print("Cannot export model from pytorch to ONNX - with version ", torch.__version__)
131 # leave no .onnx behind: which the parent process treats as a RuntimeError
135data = np.load(dataFile)
136for modelName in modelNames:
137 model = CreateModel(4, 64)
138 TrainModel(model, data["x_train"], data["y_train"])
139 ExportModel(model, modelName)
148 sigData =
df1.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
154 print(
"size of data", data_sig_size)
158 bkgData =
df2.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
172 x_train = inputs_data[idx[:ntrain]]
173 y_train = inputs_targets[idx[:ntrain]].
reshape(-1, 1)
174 x_test = inputs_data[idx[ntrain:]]
175 y_test = inputs_targets[idx[ntrain:]].
reshape(-1, 1)
177 return x_train, y_train, x_test, y_test
183 dataFile =
"Higgs_Model_train_data.npz"
184 np.savez(dataFile, x_train=x_train, y_train=y_train)
189 modelFiles = [name +
".onnx" for name
in modelNames]
190 for modelFile
in modelFiles:
192 raise RuntimeError(
"ONNX model " + modelFile +
" could not be exported")
198x_train, y_train, x_test, y_test = PrepareData()
204modelNames = [
"Higgs_Model_4L_50",
"Higgs_Model_4L_200",
"Higgs_Model_2L_500"]
205model1, model2, model3 =
TrainModels(x_train, y_train, modelNames)
214 print(
"Generating inference code for the ONNX model from ", modelFile,
"in the header ", generatedHeaderFile)
220 return generatedHeaderFile
223generatedHeaderFile =
"Higgs_Model.hxx"
226 print(
"removing existing file", generatedHeaderFile)
229weightFile =
"Higgs_Model.root"
231 print(
"removing existing file", weightFile)
248hs1 =
ROOT.TH1D(
"hs1",
"Signal result 4L 50", 100, 0, 1)
249hs2 =
ROOT.TH1D(
"hs2",
"Signal result 4L 200", 100, 0, 1)
250hs3 =
ROOT.TH1D(
"hs3",
"Signal result 2L 500", 100, 0, 1)
252hb1 =
ROOT.TH1D(
"hb1",
"Background result 4L 50", 100, 0, 1)
253hb2 =
ROOT.TH1D(
"hb2",
"Background result 4L 200", 100, 0, 1)
254hb3 =
ROOT.TH1D(
"hb3",
"Background result 2L 500", 100, 0, 1)
263 result1 =
EvalModel(session1, x_test[i, :])
264 result2 =
EvalModel(session2, x_test[i, :])
265 result3 =
EvalModel(session3, x_test[i, :])
300 for i
in range(0, n):
307 xs, ws = GetContent(hs)
308 xb, wb = GetContent(hb)
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...