diff --git a/README/ReleaseNotes/v640/index.md b/README/ReleaseNotes/v640/index.md index cb523d2794bd9..1b0498692bd5e 100644 --- a/README/ReleaseNotes/v640/index.md +++ b/README/ReleaseNotes/v640/index.md @@ -39,6 +39,7 @@ The following people have contributed to this new version: * Comparing C++ `nullptr` objects with `None` in Python now raises a `TypeError`, as announced in the ROOT 6.38 release notes. Use truth-value checks like `if not x` or `x is None` instead. * The `TGLIncludes.h` and `TGLWSIncludes.h` that were deprecated in ROOT 6.38 and scheduled for removal are gone now. Please include your required headers like `` or `` directly. * The GLEW headers (`GL/eglew.h`, `GL/glew.h`, `GL/glxew.h`, and `GL/wglew.h`) that were installed when building ROOT with `builtin_glew=ON` are no longer installed. This is done because ROOT is moving away from GLEW for loading OpenGL extensions. +* The TMVA `PyKeras` method is deprecated. It was broken by the API changes in Keras 3, released in November 2023 and part of TensorFlow 2.16 or newer. The `PyKeras` method will be removed in ROOT 6.42 (unless an updated implementation for Keras 3 that matches usage, performance and stability requirements will be found unexpectedly). ## Build System diff --git a/tmva/pymva/CMakeLists.txt b/tmva/pymva/CMakeLists.txt index 89ed2de8f754f..fda34f0910c06 100644 --- a/tmva/pymva/CMakeLists.txt +++ b/tmva/pymva/CMakeLists.txt @@ -36,4 +36,7 @@ ROOT_STANDARD_LIBRARY_PACKAGE(PyMVA TMVA ) +# To avoid deprecation warnings during build of ROOT. +target_compile_definitions(PyMVA PUBLIC PYMVA_BUILDS_ITSELF) + ROOT_ADD_TEST_SUBDIRECTORY(test) diff --git a/tmva/pymva/src/MethodPyKeras.cxx b/tmva/pymva/src/MethodPyKeras.cxx index 38ee5d5185953..731bf8119ba05 100644 --- a/tmva/pymva/src/MethodPyKeras.cxx +++ b/tmva/pymva/src/MethodPyKeras.cxx @@ -182,6 +182,10 @@ void MethodPyKeras::InitKeras() { // initialize first Keras. This is done only here when class has // all state variable set from options or read from XML file // Import Keras + Log() << kWARNING + << "The PyKeras TMVA method was deprecated in ROOT 6.40 and will be removed in ROOT 6.42, since it was broken " + "by the API changes in Keras 3, released in November 2023 and part of TensorFlow 2.16 or newer." + << Endl; if (fUseTFKeras) Log() << kINFO << "Setting up tf.keras" << Endl; diff --git a/tmva/tmva/inc/TMVA/Types.h b/tmva/tmva/inc/TMVA/Types.h index 6f019e808a6cd..3428543520b22 100644 --- a/tmva/tmva/inc/TMVA/Types.h +++ b/tmva/tmva/inc/TMVA/Types.h @@ -42,6 +42,8 @@ #include "RtypesCore.h" +#include // for R__DEPRECATED + #include "TString.h" namespace TMVA { @@ -100,7 +102,12 @@ namespace TMVA { kPyRandomForest , kPyAdaBoost , kPyGTB , +#ifdef PYMVA_BUILDS_ITSELF kPyKeras , +#else + kPyKeras + R__DEPRECATED(6, 42, "the PyKeras method is dropped since it didn't support Keras 3 (TensorFlow 2.16+)"), +#endif kPyTorch , kC50 , kRSNNS , diff --git a/tutorials/CMakeLists.txt b/tutorials/CMakeLists.txt index 59ea6e78103be..146f1fe7bffa9 100644 --- a/tutorials/CMakeLists.txt +++ b/tutorials/CMakeLists.txt @@ -326,7 +326,7 @@ if(NOT TARGET Gui) endif() if (NOT ROOT_tmva_FOUND) - list(APPEND tmva_veto machine_learning/*.C machine_learning/*.py machine_learning/envelope/*.C machine_learning/keras/*.C machine_learning/keras/*.py machine_learning/pytorch/*.py ) + list(APPEND tmva_veto machine_learning/*.C machine_learning/*.py machine_learning/envelope/*.C machine_learning/pytorch/*.py ) else() #copy input data files configure_file(${CMAKE_CURRENT_SOURCE_DIR}/machine_learning/data/tmva_class_example.root ${CMAKE_CURRENT_BINARY_DIR}/machine_learning/data COPYONLY) @@ -650,10 +650,6 @@ set (machine_learning-TMVA_SOFIE_RDataFrame_JIT-depends tutorial-machine_learnin set (machine_learning-TMVA_SOFIE_Keras_HiggsModel-depends tutorial-machine_learning-TMVA_SOFIE_RDataFrame_JIT) set (machine_learning-TMVA_SOFIE_RDataFrame-depends tutorial-machine_learning-TMVA_SOFIE_Keras_HiggsModel) set (machine_learning-TMVA_SOFIE_Inference-depends tutorial-machine_learning-TMVA_SOFIE_RDataFrame) -set (machine_learning-keras-RegressionKeras-depends tutorial-machine_learning-pytorch-RegressionPyTorch-py) -set (machine_learning-keras-ClassificationKeras-depends tutorial-machine_learning-pytorch-ClassificationPyTorch-py) -set (machine_learning-keras-ApplicationRegressionKeras-depends tutorial-machine_learning-keras-RegressionKeras-py) -set (machine_learning-keras-ApplicationClassificationKeras-depends tutorial-machine_learning-keras-ClassificationKeras-py) #--List long-running tutorials to label them as "longtest" set (long_running @@ -846,11 +842,6 @@ if(ROOT_pyroot_FOUND) # Disable tutorial showing connection to the HTCondor service at CERN list(APPEND pyveto analysis/dataframe/distrdf004_dask_lxbatch.py) - if(NOT tmva-pymva) - file(GLOB tmva_veto_py RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} machine_learning/keras/*.py) - list(APPEND pyveto ${tmva_veto_py}) - endif() - if (ROOT_KERAS_FOUND) set (machine_learning-TMVA_SOFIE_RDataFrame-py-depends tutorial-machine_learning-TMVA_SOFIE_Keras_HiggsModel) endif() @@ -953,7 +944,6 @@ if(ROOT_pyroot_FOUND) machine_learning/TMVA_SOFIE_Inference.py machine_learning/TMVA_SOFIE_Models.py machine_learning/TMVA_SOFIE_RDataFrame.py - machine_learning/keras/*.py ) file(GLOB requires_torch RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} machine_learning/pytorch/*.py diff --git a/tutorials/machine_learning/keras/ApplicationClassificationKeras.py b/tutorials/machine_learning/keras/ApplicationClassificationKeras.py deleted file mode 100755 index 85c7882fb75e4..0000000000000 --- a/tutorials/machine_learning/keras/ApplicationClassificationKeras.py +++ /dev/null @@ -1,47 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to apply a trained model to new data. -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from ROOT import TMVA, TFile, TString, gROOT -from array import array -from subprocess import call -from os.path import isfile - -# Setup TMVA -TMVA.Tools.Instance() -TMVA.PyMethodBase.PyInitialize() -reader = TMVA.Reader("Color:!Silent") - -# Load data -data = TFile.Open(str(gROOT.GetTutorialDir()) + "/machine_learning/data/tmva_class_example.root") -signal = data.Get('TreeS') -background = data.Get('TreeB') - -branches = {} -for branch in signal.GetListOfBranches(): - branchName = branch.GetName() - branches[branchName] = array('f', [-999]) - reader.AddVariable(branchName, branches[branchName]) - signal.SetBranchAddress(branchName, branches[branchName]) - background.SetBranchAddress(branchName, branches[branchName]) - -# Book methods -reader.BookMVA('PyKeras', TString('dataset/weights/TMVAClassification_PyKeras.weights.xml')) - -# Print some example classifications -print('Some signal example classifications:') -for i in range(20): - signal.GetEntry(i) - print(reader.EvaluateMVA('PyKeras')) -print('') - -print('Some background example classifications:') -for i in range(20): - background.GetEntry(i) - print(reader.EvaluateMVA('PyKeras')) diff --git a/tutorials/machine_learning/keras/ApplicationRegressionKeras.py b/tutorials/machine_learning/keras/ApplicationRegressionKeras.py deleted file mode 100755 index 7055236e23047..0000000000000 --- a/tutorials/machine_learning/keras/ApplicationRegressionKeras.py +++ /dev/null @@ -1,40 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to apply a trained model to new data (regression). -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from ROOT import TMVA, TFile, TString, gROOT -from array import array -from subprocess import call -from os.path import isfile - -# Setup TMVA -TMVA.Tools.Instance() -TMVA.PyMethodBase.PyInitialize() -reader = TMVA.Reader("Color:!Silent") - -# Load data -data = TFile.Open(str(gROOT.GetTutorialDir()) + '/machine_learning/data/tmva_reg_example.root') -tree = data.Get('TreeR') - -branches = {} -for branch in tree.GetListOfBranches(): - branchName = branch.GetName() - branches[branchName] = array('f', [-999]) - tree.SetBranchAddress(branchName, branches[branchName]) - if branchName != 'fvalue': - reader.AddVariable(branchName, branches[branchName]) - -# Book methods -reader.BookMVA('PyKeras', TString('dataset/weights/TMVARegression_PyKeras.weights.xml')) - -# Print some example regressions -print('Some example regressions:') -for i in range(20): - tree.GetEntry(i) - print('True/MVA value: {}/{}'.format(branches['fvalue'][0],reader.EvaluateMVA('PyKeras'))) diff --git a/tutorials/machine_learning/keras/ClassificationKeras.py b/tutorials/machine_learning/keras/ClassificationKeras.py deleted file mode 100755 index 3baad783676e9..0000000000000 --- a/tutorials/machine_learning/keras/ClassificationKeras.py +++ /dev/null @@ -1,76 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to do classification in TMVA with neural networks -## trained with keras. -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from ROOT import TMVA, TFile, TCut, gROOT -from subprocess import call -from os.path import isfile - -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense -from tensorflow.keras.optimizers import SGD - - -def create_model(): - # Generate model - - # Define model - model = Sequential() - model.add(Dense(64, activation='relu', input_dim=4)) - model.add(Dense(2, activation='softmax')) - - # Set loss and optimizer - model.compile(loss='categorical_crossentropy', - optimizer=SGD(learning_rate=0.01), weighted_metrics=['accuracy', ]) - - # Store model to file - model.save('modelClassification.h5') - model.summary() - - -def run(): - with TFile.Open('TMVA_Classification_Keras.root', 'RECREATE') as output, TFile.Open(str(gROOT.GetTutorialDir()) + '/machine_learning/data/tmva_class_example.root') as data: - factory = TMVA.Factory('TMVAClassification', output, - '!V:!Silent:Color:DrawProgressBar:Transformations=D,G:AnalysisType=Classification') - - signal = data.Get('TreeS') - background = data.Get('TreeB') - - dataloader = TMVA.DataLoader('dataset') - for branch in signal.GetListOfBranches(): - dataloader.AddVariable(branch.GetName()) - - dataloader.AddSignalTree(signal, 1.0) - dataloader.AddBackgroundTree(background, 1.0) - dataloader.PrepareTrainingAndTestTree(TCut(''), - 'nTrain_Signal=4000:nTrain_Background=4000:SplitMode=Random:NormMode=NumEvents:!V') - - # Book methods - factory.BookMethod(dataloader, TMVA.Types.kFisher, 'Fisher', - '!H:!V:Fisher:VarTransform=D,G') - factory.BookMethod(dataloader, TMVA.Types.kPyKeras, 'PyKeras', - 'H:!V:VarTransform=D,G:FilenameModel=modelClassification.h5:FilenameTrainedModel=trainedModelClassification.h5:NumEpochs=20:BatchSize=32:LearningRateSchedule=10,0.01;20,0.005') - - # Run training, test and evaluation - factory.TrainAllMethods() - factory.TestAllMethods() - factory.EvaluateAllMethods() - - -if __name__ == "__main__": - # Setup TMVA - TMVA.Tools.Instance() - TMVA.PyMethodBase.PyInitialize() - - # Create and store the ML model - create_model() - - # Run TMVA - run() diff --git a/tutorials/machine_learning/keras/GenerateModel.py b/tutorials/machine_learning/keras/GenerateModel.py deleted file mode 100755 index 832d54e410dc2..0000000000000 --- a/tutorials/machine_learning/keras/GenerateModel.py +++ /dev/null @@ -1,62 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to define and generate a keras model for use with -## TMVA. -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense, Activation -from tensorflow.keras.regularizers import l2 -from tensorflow.keras.optimizers import SGD -from tensorflow.keras.utils import plot_model - -# Setup the model here -num_input_nodes = 4 -num_output_nodes = 2 -num_hidden_layers = 1 -nodes_hidden_layer = 64 -l2_val = 1e-5 - -model = Sequential() - -# Hidden layer 1 -# NOTE: Number of input nodes need to be defined in this layer -model.add(Dense(nodes_hidden_layer, activation='relu', kernel_regularizer=l2(l2_val), input_dim=num_input_nodes)) - -# Hidden layer 2 to num_hidden_layers -# NOTE: Here, you can do what you want -for k in range(num_hidden_layers-1): - model.add(Dense(nodes_hidden_layer, activation='relu', kernel_regularizer=l2(l2_val))) - -# Output layer -# NOTE: Use following output types for the different tasks -# Binary classification: 2 output nodes with 'softmax' activation -# Regression: 1 output with any activation ('linear' recommended) -# Multiclass classification: (number of classes) output nodes with 'softmax' activation -model.add(Dense(num_output_nodes, activation='softmax')) - -# Compile model -# NOTE: Use following settings for the different tasks -# Any classification: 'categorical_crossentropy' is recommended loss function -# Regression: 'mean_squared_error' is recommended loss function -model.compile(loss='categorical_crossentropy', optimizer=SGD(learning_rate=0.01), weighted_metrics=['accuracy',]) - -# Save model -model.save('model.h5') - -# Additional information about the model -# NOTE: This is not needed to run the model - -# Print summary -model.summary() - -# Visualize model as graph -try: - plot_model(model, to_file='model.png', show_shapes=True) -except: - print('[INFO] Failed to make model plot') diff --git a/tutorials/machine_learning/keras/MulticlassKeras.py b/tutorials/machine_learning/keras/MulticlassKeras.py deleted file mode 100755 index 358b8197f9bd2..0000000000000 --- a/tutorials/machine_learning/keras/MulticlassKeras.py +++ /dev/null @@ -1,84 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to do multiclass classification in TMVA with neural -## networks trained with keras. -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from ROOT import TMVA, TFile, TCut, gROOT -from os.path import isfile - -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense -from tensorflow.keras.optimizers import SGD - - -def create_model(): - # Define model - model = Sequential() - model.add(Dense(32, activation='relu', input_dim=4)) - model.add(Dense(4, activation='softmax')) - - # Set loss and optimizer - model.compile(loss='categorical_crossentropy', optimizer=SGD( - learning_rate=0.01), weighted_metrics=['accuracy',]) - - # Store model to file - model.save('modelMultiClass.h5') - model.summary() - - -def run(): - with TFile.Open('TMVA.root', 'RECREATE') as output, TFile.Open('tmva_example_multiple_background.root') as data: - factory = TMVA.Factory('TMVAClassification', output, - '!V:!Silent:Color:DrawProgressBar:Transformations=D,G:AnalysisType=multiclass') - - signal = data.Get('TreeS') - background0 = data.Get('TreeB0') - background1 = data.Get('TreeB1') - background2 = data.Get('TreeB2') - - dataloader = TMVA.DataLoader('dataset') - for branch in signal.GetListOfBranches(): - dataloader.AddVariable(branch.GetName()) - - dataloader.AddTree(signal, 'Signal') - dataloader.AddTree(background0, 'Background_0') - dataloader.AddTree(background1, 'Background_1') - dataloader.AddTree(background2, 'Background_2') - dataloader.PrepareTrainingAndTestTree(TCut(''), - 'SplitMode=Random:NormMode=NumEvents:!V') - - # Book methods - factory.BookMethod(dataloader, TMVA.Types.kFisher, 'Fisher', - '!H:!V:Fisher:VarTransform=D,G') - factory.BookMethod(dataloader, TMVA.Types.kPyKeras, 'PyKeras', - 'H:!V:VarTransform=D,G:FilenameModel=modelMultiClass.h5:FilenameTrainedModel=trainedModelMultiClass.h5:NumEpochs=20:BatchSize=32') - - # Run TMVA - factory.TrainAllMethods() - factory.TestAllMethods() - factory.EvaluateAllMethods() - - -if __name__ == "__main__": - # Generate model - create_model() - - # Setup TMVA - TMVA.Tools.Instance() - TMVA.PyMethodBase.PyInitialize() - - # Load data - if not isfile('tmva_example_multiple_background.root'): - createDataMacro = str(gROOT.GetTutorialDir()) + '/machine_learning/createData.C' - print(createDataMacro) - gROOT.ProcessLine('.L {}'.format(createDataMacro)) - gROOT.ProcessLine('create_MultipleBackground(4000)') - - # Run TMVA - run() diff --git a/tutorials/machine_learning/keras/RegressionKeras.py b/tutorials/machine_learning/keras/RegressionKeras.py deleted file mode 100755 index dce84773d8b7f..0000000000000 --- a/tutorials/machine_learning/keras/RegressionKeras.py +++ /dev/null @@ -1,77 +0,0 @@ -## \file -## \ingroup tutorial_tmva_keras -## \notebook -nodraw -## This tutorial shows how to do regression in TMVA with neural networks -## trained with keras. -## -## \macro_code -## -## \date 2017 -## \author TMVA Team - -from ROOT import TMVA, TFile, TCut, gROOT -from subprocess import call -from os.path import isfile - -from tensorflow.keras.models import Sequential -from tensorflow.keras.layers import Dense -from tensorflow.keras.optimizers import SGD - - -def create_model(): - # Define model - model = Sequential() - model.add(Dense(64, activation='tanh', input_dim=2)) - model.add(Dense(1, activation='linear')) - - # Set loss and optimizer - model.compile(loss='mean_squared_error', optimizer=SGD( - learning_rate=0.01), weighted_metrics=[]) - - # Store model to file - model.save('modelRegression.h5') - model.summary() - - -def run(): - - with TFile.Open('TMVA_Regression_Keras.root', 'RECREATE') as output, TFile.Open(str(gROOT.GetTutorialDir()) + '/machine_learning/data/tmva_reg_example.root') as data: - factory = TMVA.Factory('TMVARegression', output, - '!V:!Silent:Color:DrawProgressBar:Transformations=D,G:AnalysisType=Regression') - - tree = data.Get('TreeR') - - dataloader = TMVA.DataLoader('dataset') - for branch in tree.GetListOfBranches(): - name = branch.GetName() - if name != 'fvalue': - dataloader.AddVariable(name) - dataloader.AddTarget('fvalue') - - dataloader.AddRegressionTree(tree, 1.0) - # use only 1000 events since evaluation is very slow (especially on MacOS). Increase it to get meaningful results - dataloader.PrepareTrainingAndTestTree(TCut(''), - 'nTrain_Regression=1000:SplitMode=Random:NormMode=NumEvents:!V') - - # Book methods - factory.BookMethod(dataloader, TMVA.Types.kPyKeras, 'PyKeras', - 'H:!V:VarTransform=D,G:FilenameModel=modelRegression.h5:FilenameTrainedModel=trainedModelRegression.h5:NumEpochs=20:BatchSize=32') - factory.BookMethod(dataloader, TMVA.Types.kBDT, 'BDTG', - '!H:!V:VarTransform=D,G:NTrees=1000:BoostType=Grad:Shrinkage=0.1:UseBaggedBoost:BaggedSampleFraction=0.5:nCuts=20:MaxDepth=4') - - # Run TMVA - factory.TrainAllMethods() - factory.TestAllMethods() - factory.EvaluateAllMethods() - - -if __name__ == "__main__": - # Setup TMVA - TMVA.Tools.Instance() - TMVA.PyMethodBase.PyInitialize() - - # Generate model - create_model() - - # Run TMVA - run() diff --git a/tutorials/machine_learning/keras/index.md b/tutorials/machine_learning/keras/index.md deleted file mode 100644 index 3f5b7d4e01462..0000000000000 --- a/tutorials/machine_learning/keras/index.md +++ /dev/null @@ -1,3 +0,0 @@ -\defgroup tutorial_tmva_keras TMVA Keras tutorials -\ingroup tutorial_ml -\brief Example code which illustrates how to use keras with the python interface of TMVA