Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions tmva/pymva/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ endif(ROOT_SKLEARN_FOUND)

# Enable tests based on available python modules
if(ROOT_TORCH_FOUND)
configure_file(generatePyTorchModelClassification.py generatePyTorchModelClassification.py COPYONLY)
configure_file(generatePyTorchModelMulticlass.py generatePyTorchModelMulticlass.py COPYONLY)
configure_file(generatePyTorchModelRegression.py generatePyTorchModelRegression.py COPYONLY)

# Test PyTorch: Binary classification

if (ROOT_SKLEARN_FOUND)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
from torch import nn

# Define model
model = nn.Sequential(
nn.Linear(4, 64),
nn.ReLU(),
nn.Linear(64, 2),
nn.Softmax(dim=1))
model = nn.Sequential(nn.Linear(4, 64), nn.ReLU(), nn.Linear(64, 2), nn.Softmax(dim=1))

# Construct loss function and Optimizer.
criterion = torch.nn.MSELoss()
Expand All @@ -33,8 +29,8 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

# print train statistics
running_train_loss += train_loss.item()
if i % 32 == 31: # print every 32 mini-batches
print(f"[{epoch+1}, {i+1}] train loss: {running_train_loss / 32 :.3f}")
if i % 32 == 31: # print every 32 mini-batches
print(f"[{epoch + 1}, {i + 1}] train loss: {running_train_loss / 32:.3f}")
running_train_loss = 0.0

if schedule:
Expand All @@ -51,23 +47,23 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

curr_val = running_val_loss / len(val_loader)
if save_best:
if best_val==None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)
if best_val is None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)

# print val statistics per epoch
print(f"[{epoch+1}] val loss: {curr_val :.3f}")
print(f"[{epoch + 1}] val loss: {curr_val:.3f}")
running_val_loss = 0.0

print(f"Finished Training on {epoch+1} Epochs!")
print(f"Finished Training on {epoch + 1} Epochs!")

return model


def predict(model, test_X, batch_size=32):
# Set to eval mode
model.eval()

test_dataset = torch.utils.data.TensorDataset(torch.Tensor(test_X))
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

Expand All @@ -78,13 +74,12 @@ def predict(model, test_X, batch_size=32):
outputs = model(X)
predictions.append(outputs)
preds = torch.cat(predictions)

return preds.numpy()


load_model_custom_objects = {"optimizer": optimizer, "criterion": criterion, "train_func": fit, "predict_func": predict}

# Store model to file
m = torch.jit.script(model)
torch.jit.save(m,"PyTorchModelClassification.pt")

torch.jit.save(m, "PyTorchModelClassification.pt")
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
from torch import nn

# Define model
model = nn.Sequential(
nn.Linear(4, 64),
nn.ReLU(),
nn.Linear(64, 4),
nn.Softmax(dim=1))
model = nn.Sequential(nn.Linear(4, 64), nn.ReLU(), nn.Linear(64, 4), nn.Softmax(dim=1))

# Construct loss function and Optimizer.
criterion = nn.CrossEntropyLoss()
Expand Down Expand Up @@ -34,8 +30,8 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

# print train statistics
running_train_loss += train_loss.item()
if i % 4 == 3: # print every 4 mini-batches
print(f"[{epoch+1}, {i+1}] train loss: {running_train_loss / 4 :.3f}")
if i % 4 == 3: # print every 4 mini-batches
print(f"[{epoch + 1}, {i + 1}] train loss: {running_train_loss / 4:.3f}")
running_train_loss = 0.0

if schedule:
Expand All @@ -53,23 +49,23 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

curr_val = running_val_loss / len(val_loader)
if save_best:
if best_val==None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)
if best_val is None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)

# print val statistics per epoch
print(f"[{epoch+1}] val loss: {curr_val :.3f}")
print(f"[{epoch + 1}] val loss: {curr_val:.3f}")
running_val_loss = 0.0

print(f"Finished Training on {epoch+1} Epochs!")
print(f"Finished Training on {epoch + 1} Epochs!")

return model


def predict(model, test_X, batch_size=32):
# Set to eval mode
model.eval()

test_dataset = torch.utils.data.TensorDataset(torch.Tensor(test_X))
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

Expand All @@ -80,13 +76,12 @@ def predict(model, test_X, batch_size=32):
outputs = model(X)
predictions.append(outputs)
preds = torch.cat(predictions)

return preds.numpy()


load_model_custom_objects = {"optimizer": optimizer, "criterion": criterion, "train_func": fit, "predict_func": predict}

# Store model to file
m = torch.jit.script(model)
torch.jit.save(m,"PyTorchModelMulticlass.pt")

torch.jit.save(m, "PyTorchModelMulticlass.pt")
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
from torch import nn

# Define model
model = nn.Sequential(
nn.Linear(2, 64),
nn.Tanh(),
nn.Linear(64, 1))
model = nn.Sequential(nn.Linear(2, 64), nn.Tanh(), nn.Linear(64, 1))

# Construct loss function and Optimizer.
criterion = torch.nn.MSELoss()
Expand All @@ -32,8 +29,8 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

# print train statistics
running_train_loss += train_loss.item()
if i % 32 == 31: # print every 32 mini-batches
print(f"[{epoch+1}, {i+1}] train loss: {running_train_loss / 32 :.3f}")
if i % 32 == 31: # print every 32 mini-batches
print(f"[{epoch + 1}, {i + 1}] train loss: {running_train_loss / 32:.3f}")
running_train_loss = 0.0

if schedule:
Expand All @@ -50,23 +47,23 @@ def fit(model, train_loader, val_loader, num_epochs, batch_size, optimizer, crit

curr_val = running_val_loss / len(val_loader)
if save_best:
if best_val==None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)
if best_val is None:
best_val = curr_val
best_val = save_best(model, curr_val, best_val)

# print val statistics per epoch
print(f"[{epoch+1}] val loss: {curr_val :.3f}")
print(f"[{epoch + 1}] val loss: {curr_val:.3f}")
running_val_loss = 0.0

print(f"Finished Training on {epoch+1} Epochs!")
print(f"Finished Training on {epoch + 1} Epochs!")

return model


def predict(model, test_X, batch_size=32):
# Set to eval mode
model.eval()

test_dataset = torch.utils.data.TensorDataset(torch.Tensor(test_X))
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

Expand All @@ -77,12 +74,12 @@ def predict(model, test_X, batch_size=32):
outputs = model(X)
predictions.append(outputs)
preds = torch.cat(predictions)

return preds.numpy()


load_model_custom_objects = {"optimizer": optimizer, "criterion": criterion, "train_func": fit, "predict_func": predict}

# Store model to file
m = torch.jit.script(model)
torch.jit.save(m,"PyTorchModelRegression.pt")
torch.jit.save(m, "PyTorchModelRegression.pt")
3 changes: 0 additions & 3 deletions tmva/sofie/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,6 @@ endif()

# Any features that link against libpython are disabled if built with tpython=OFF
if (tpython AND ROOT_TORCH_FOUND AND ROOT_ONNX_FOUND AND BLAS_FOUND AND NOT broken_onnx)
configure_file(generatePyTorchModelClassification.py generatePyTorchModelClassification.py COPYONLY)
configure_file(generatePyTorchModelMulticlass.py generatePyTorchModelMulticlass.py COPYONLY)
configure_file(generatePyTorchModelRegression.py generatePyTorchModelRegression.py COPYONLY)
configure_file(generatePyTorchModels.py generatePyTorchModels.py COPYONLY)

# Test RModelParser_PyTorch
Expand Down
28 changes: 23 additions & 5 deletions tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -345,25 +345,43 @@ else()
ROOT_FIND_PYTHON_MODULE(keras)
ROOT_FIND_PYTHON_MODULE(sonnet)
ROOT_FIND_PYTHON_MODULE(graph_nets)

# Check if we support the installed Keras version. Otherwise, veto SOFIE
# Keras tutorials. This mirrors the logic in tmva/sofie/test/CMakeLists.txt.
# TODO: make sure we also support the newest Keras
set(unsupported_keras_version "3.5.0")
if (NOT DEFINED ROOT_KERAS_VERSION)
message(WARNING "Keras found, but version unknown — cannot verify compatibility.")
elseif (NOT ROOT_KERAS_VERSION VERSION_LESS ${unsupported_keras_version})
message(WARNING "Keras version ${ROOT_KERAS_VERSION} is too new for the SOFIE Keras parser (only supports < ${unsupported_keras_version}). Corresponding tutorials will not be tested.")
set(keras_unsupported TRUE)
endif()

if (NOT BLAS_FOUND)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_GNN_Application.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RSofieReader.C)
endif()
if (NOT tmva-pymva OR NOT ROOT_KERAS_FOUND)
if (NOT tmva-sofie OR NOT ROOT_KERAS_FOUND OR keras_unsupported)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Keras.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Models.py)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Keras_HiggsModel.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame_JIT.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RSofieReader.C)
endif()
if (NOT tmva-pymva OR NOT ROOT_TORCH_FOUND)
if (NOT tmva-pymva)
# These SOFIE tutorials take models trained via PyMVA-PyKeras as input
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Keras_HiggsModel.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame.C)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame.py)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RSofieReader.C)
endif()
if (NOT tmva-sofie OR NOT ROOT_TORCH_FOUND)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_PyTorch.C)
endif()
# The following tutorials use PyMVA functionality
if (NOT tmva-pymva)
if (NOT tmva-sofie)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_RDataFrame.py)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Models.py)
list(APPEND tmva_veto machine_learning/TMVA_SOFIE_Inference.py)
endif()
#veto this tutorial since it is added directly
Expand Down
6 changes: 1 addition & 5 deletions tutorials/machine_learning/TMVA_SOFIE_Inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@
### \macro_output
### \author Lorenzo Moneta

import ROOT
import numpy as np


ROOT.TMVA.PyMethodBase.PyInitialize()

import ROOT

# check if the input file exists
modelFile = "Higgs_trained_model.h5"
Expand Down
17 changes: 8 additions & 9 deletions tutorials/machine_learning/TMVA_SOFIE_Keras.C
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ model.save('KerasModel.h5')\n";

void TMVA_SOFIE_Keras(const char * modelFile = nullptr, bool printModelInfo = true){

//Running the Python script to generate Keras .h5 file
TMVA::PyMethodBase::PyInitialize();
// Running the Python script to generate Keras .h5 file

if (modelFile == nullptr) {
TMacro m;
m.AddLine(pythonSrc);
m.SaveSource("make_keras_model.py");
gSystem->Exec(TMVA::Python_Executable() + " make_keras_model.py");
modelFile = "KerasModel.h5";
}
if (modelFile == nullptr) {
TMacro m;
m.AddLine(pythonSrc);
m.SaveSource("make_keras_model.py");
gSystem->Exec("python3 make_keras_model.py");
modelFile = "KerasModel.h5";
}

//Parsing the saved Keras .h5 file into RModel object
SOFIE::RModel model = SOFIE::PyKeras::Parse(modelFile);
Expand Down
16 changes: 6 additions & 10 deletions tutorials/machine_learning/TMVA_SOFIE_Models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,17 @@
### \macro_output
### \author Lorenzo Moneta

import ROOT
from os.path import exists

ROOT.TMVA.PyMethodBase.PyInitialize()


## generate and train Keras models with different architectures
import os

import numpy as np
from tensorflow.keras.models import Sequential
import ROOT
from sklearn.model_selection import train_test_split
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam

from sklearn.model_selection import train_test_split
## generate and train Keras models with different architectures


def CreateModel(nlayers = 4, nunits = 64):
model = Sequential()
Expand Down Expand Up @@ -103,7 +100,6 @@ def GenerateModelCode(modelFile, generatedHeaderFile):

generatedHeaderFile = "Higgs_Model.hxx"
#need to remove existing header file since we are appending on same one
import os
if (os.path.exists(generatedHeaderFile)):
weightFile = "Higgs_Model.root"
print("removing existing files", generatedHeaderFile,weightFile)
Expand Down
Loading
Loading