25def CreateModel(nlayers=4, nunits=64):
28 for i
in range(nlayers):
29 layers += [nn.Linear(ninputs, nunits), nn.ReLU()]
31 layers += [nn.Linear(ninputs, 1), nn.Sigmoid()]
32 model = nn.Sequential(*layers)
37def TrainModel(model, x, y, epochs=5, batch_size=50):
38 x = torch.from_numpy(x)
39 y = torch.from_numpy(y)
40 criterion = nn.BCELoss()
41 optimizer = torch.optim.Adam(model.parameters())
42 nbatches = x.shape[0] // batch_size
43 for epoch
in range(epochs):
44 perm = torch.randperm(x.shape[0])
46 for i
in range(nbatches):
47 idx = perm[i * batch_size : (i + 1) * batch_size]
49 loss = criterion(model(x[idx]), y[idx])
52 running_loss += loss.item()
53 print(f
"Epoch {epoch + 1}/{epochs} - average loss: {running_loss / nbatches:.4f}")
56def ExportModel(model, modelName):
62 modelFile = modelName +
".onnx"
63 dummy_x = torch.randn(1, 7)
67 def filtered_kwargs(func, **candidate_kwargs):
68 sig = inspect.signature(func)
69 return {k: v
for k, v
in candidate_kwargs.items()
if k
in sig.parameters}
71 kwargs = filtered_kwargs(
73 input_names=[
"input"],
74 output_names=[
"output"],
78 print(
"calling torch.onnx.export with parameters", kwargs)
80 torch.onnx.export(model, dummy_x, modelFile, **kwargs)
82 print(
"model exported to ONNX as", modelFile)
88 inputFile = str(ROOT.gROOT.GetTutorialDir()) +
"/machine_learning/data/Higgs_data.root"
91 sigData = df1.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
95 xsig = np.column_stack(list(sigData.values()))
96 data_sig_size = xsig.shape[0]
97 print(
"size of data", data_sig_size)
101 bkgData = df2.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
102 xbkg = np.column_stack(list(bkgData.values()))
103 data_bkg_size = xbkg.shape[0]
105 ysig = np.ones(data_sig_size)
106 ybkg = np.zeros(data_bkg_size)
107 inputs_data = np.concatenate((xsig, xbkg), axis=0).astype(np.float32)
108 inputs_targets = np.concatenate((ysig, ybkg), axis=0).astype(np.float32)
111 rng = np.random.default_rng(1234)
112 idx = rng.permutation(inputs_data.shape[0])
113 ntrain = inputs_data.shape[0] // 2
115 x_train = inputs_data[idx[:ntrain]]
116 y_train = inputs_targets[idx[:ntrain]].reshape(-1, 1)
117 x_test = inputs_data[idx[ntrain:]]
118 y_test = inputs_targets[idx[ntrain:]].reshape(-1, 1)
120 return x_train, y_train, x_test, y_test
123def TrainModels(x_train, y_train, modelNames):
126 for modelName
in modelNames:
127 model = CreateModel(4, 64)
128 TrainModel(model, x_train, y_train)
129 modelFiles.append(ExportModel(model, modelName))
135x_train, y_train, x_test, y_test = PrepareData()
141modelNames = [
"Higgs_Model_4L_50",
"Higgs_Model_4L_200",
"Higgs_Model_2L_500"]
142model1, model2, model3 = TrainModels(x_train, y_train, modelNames)
147def GenerateModelCode(modelFile, generatedHeaderFile, weightFile):
148 parser = ROOT.TMVA.Experimental.SOFIE.RModelParser_ONNX()
149 model = parser.Parse(modelFile)
151 print(
"Generating inference code for the ONNX model from ", modelFile,
"in the header ", generatedHeaderFile)
154 model.Generate(ROOT.TMVA.Experimental.SOFIE.Options.kSafetensorsWeightFile)
156 model.OutputGenerated(generatedHeaderFile,
True)
159 os.replace(generatedHeaderFile.replace(
".hxx",
".safetensors"), weightFile)
161 return generatedHeaderFile
164generatedHeaderFile =
"Higgs_Model.hxx"
166if os.path.exists(generatedHeaderFile):
167 print(
"removing existing file", generatedHeaderFile)
168 os.remove(generatedHeaderFile)
170weightFiles = [name +
".safetensors" for name
in modelNames]
171for weightFile
in weightFiles:
172 if os.path.exists(weightFile):
173 print(
"removing existing file", weightFile)
174 os.remove(weightFile)
176GenerateModelCode(model1, generatedHeaderFile, weightFiles[0])
177GenerateModelCode(model2, generatedHeaderFile, weightFiles[1])
178GenerateModelCode(model3, generatedHeaderFile, weightFiles[2])
182ROOT.gInterpreter.Declare(
'#include "' + generatedHeaderFile +
'"')
186session1 = ROOT.TMVA_SOFIE_Higgs_Model_4L_50.Session(weightFiles[0])
187session2 = ROOT.TMVA_SOFIE_Higgs_Model_4L_200.Session(weightFiles[1])
188session3 = ROOT.TMVA_SOFIE_Higgs_Model_2L_500.Session(weightFiles[2])
190hs1 = ROOT.TH1D(
"hs1",
"Signal result 4L 50", 100, 0, 1)
191hs2 = ROOT.TH1D(
"hs2",
"Signal result 4L 200", 100, 0, 1)
192hs3 = ROOT.TH1D(
"hs3",
"Signal result 2L 500", 100, 0, 1)
194hb1 = ROOT.TH1D(
"hb1",
"Background result 4L 50", 100, 0, 1)
195hb2 = ROOT.TH1D(
"hb2",
"Background result 4L 200", 100, 0, 1)
196hb3 = ROOT.TH1D(
"hb3",
"Background result 2L 500", 100, 0, 1)
199def EvalModel(session, x):
200 result = session.infer(x)
204for i
in range(0, x_test.shape[0]):
205 result1 = EvalModel(session1, x_test[i, :])
206 result2 = EvalModel(session2, x_test[i, :])
207 result3 = EvalModel(session3, x_test[i, :])
218def PlotHistos(hs, hb):
219 hs.SetLineColor(
"kRed")
220 hb.SetLineColor(
"kBlue")
240 x = ROOT.std.vector[
"float"](n)
241 w = ROOT.std.vector[
"float"](n)
242 for i
in range(0, n):
243 x[i] = h.GetBinCenter(i + 1)
244 w[i] = h.GetBinContent(i + 1)
248def MakeROCCurve(hs, hb):
249 xs, ws = GetContent(hs)
250 xb, wb = GetContent(hb)
251 roc = ROOT.TMVA.ROCCurve(xs, xb, ws, wb)
252 print(
"ROC integral for ", hs.GetName(), roc.GetROCIntegral())
253 curve = roc.GetROCCurve()
254 curve.SetName(hs.GetName())
260r1, curve1 = MakeROCCurve(hs1, hb1)
261curve1.SetLineColor(
"kRed")
264r2, curve2 = MakeROCCurve(hs2, hb2)
265curve2.SetLineColor(
"kBlue")
268r3, curve3 = MakeROCCurve(hs3, hb3)
269curve3.SetLineColor(
"kGreen")
ROOT's RDataFrame offers a modern, high-level interface for analysis of data stored in TTree ,...