42modelName = sys.argv[2]
45@contextlib.contextmanager
46def expect_warning(category, message):
47 # Silence a known third-party warning and raise if it stops firing.
49 # Notifies us to drop the workaround once the upstream library is fixed.
50 with warnings.catch_warnings(record=True) as caught:
51 warnings.simplefilter("always")
55 if issubclass(w.category, category) and message in str(w.message):
58 warnings.warn_explicit(w.message, w.category, w.filename, w.lineno)
61 f"Expected {category.__name__} containing {message!r} was not "
62 "emitted. This tutorial's workaround can probably be removed."
66def CreateModel(nlayers=4, nunits=64):
69 for i in range(1, nlayers):
70 layers += [nn.Linear(ninputs, nunits), nn.ReLU()]
72 layers += [nn.Linear(ninputs, 1), nn.Sigmoid()]
73 model = nn.Sequential(*layers)
78def TrainModel(model, x, y, epochs=5, batch_size=50):
79 x = torch.from_numpy(x)
80 y = torch.from_numpy(y)
81 criterion = nn.BCELoss()
82 optimizer = torch.optim.Adam(model.parameters())
83 nbatches = x.shape[0] // batch_size
84 for epoch in range(epochs):
85 perm = torch.randperm(x.shape[0])
87 for i in range(nbatches):
88 idx = perm[i * batch_size : (i + 1) * batch_size]
90 loss = criterion(model(x[idx]), y[idx])
93 running_loss += loss.item()
94 print(f"Epoch {epoch + 1}/{epochs} - average loss: {running_loss / nbatches:.4f}")
97def ExportModel(model, modelName):
98 # need to evaluate the model before exporting to ONNX
99 # and to provide a dummy input tensor to set the input model shape
100 # (the batch size is fixed to 1 for the SOFIE inference)
103 modelFile = modelName + ".onnx"
104 dummy_x = torch.randn(1, 7)
107 # check for torch.onnx.export parameters
108 def filtered_kwargs(func, **candidate_kwargs):
109 sig = inspect.signature(func)
110 return {k: v for k, v in candidate_kwargs.items() if k in sig.parameters}
112 kwargs = filtered_kwargs(
114 input_names=["input"],
115 output_names=["output"],
116 external_data=False, # may not exist
117 dynamo=True, # may not exist
119 print("calling torch.onnx.export with parameters", kwargs)
122 # torch.onnx.export (dynamo path) pickles its export program through
123 # copyreg, which still references the deprecated LeafSpec. The warning
124 # is emitted from inside PyTorch and cannot be avoided from user code.
125 with expect_warning(FutureWarning, "isinstance(treespec, LeafSpec)"):
126 torch.onnx.export(model, dummy_x, modelFile, **kwargs)
127 print("model exported to ONNX as", modelFile)
129 print("Cannot export model from pytorch to ONNX - with version ", torch.__version__)
130 # leave no .onnx behind: which the parent process treats as a RuntimeError
134data = np.load(dataFile)
136# create dense model with 3 layers of 64 units and train it
137model = CreateModel(3, 64)
138TrainModel(model, data["x_train"], data["y_train"])
139ExportModel(model, modelName)
141# evaluate the trained model on the validation inputs, for comparison with SOFIE
143 y = model(torch.from_numpy(data["x_check"])).numpy()
144np.save(modelName + "_torch_output.npy", y)
153 sigData =
df1.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
159 print(
"size of data", data_sig_size)
163 bkgData =
df2.AsNumpy(columns=[
"m_jj",
"m_jjj",
"m_lv",
"m_jlv",
"m_bb",
"m_wbb",
"m_wwbb"])
177 x_train = inputs_data[idx[:ntrain]]
178 y_train = inputs_targets[idx[:ntrain]].
reshape(-1, 1)
179 x_test = inputs_data[idx[ntrain:]]
180 y_test = inputs_targets[idx[ntrain:]].
reshape(-1, 1)
182 return x_train, y_train, x_test, y_test
188 dataFile = name +
"_train_data.npz"
189 np.savez(dataFile, x_train=x_train, y_train=y_train, x_check=x_check)
191 modelFile = name +
".onnx"
192 torchOutputFile = name +
"_torch_output.npy"
198 ytorch =
np.load(torchOutputFile)
200 return modelFile, ytorch
207 raise FileNotFoundError(
"Input model file is missing. The PyTorch training did not produce " + modelFile)
235modelHeaderFile = modelName +
".hxx"
253 print(
"input to model is ", x_check[i],
"\n\t -> output using SOFIE = ", y[0],
" using PyTorch = ", ytorch[i, 0])
254 if abs(y[0] - ytorch[i, 0]) > 0.01:
255 raise RuntimeError(
"ERROR: Result is different between SOFIE and PyTorch")
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 ,...
GenerateCode(modelFile="model.onnx")
TrainModel(x_train, y_train, x_check, name)