Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ml_dataloader_XGBoost.py
Go to the documentation of this file.
1## \file
2## \ingroup tutorial_ml
3## \notebook -nodraw
4## This tutorial demonstrates training a classifier model directly
5## from remote ROOT data without intermediate preparation steps,
6## using XGBoost and the RDataLoader interface.
7##
8## \macro_code
9## \macro_output
10##
11## \date July 2026
12## \author Silia Taider
13
14import ROOT
15
16variables = ["Muon_pt_1", "Muon_pt_2", "Electron_pt_1", "Electron_pt_2"]
17
18
19def filter_events(df):
20 """Reduce initial dataset to only events which shall be used for training"""
21 return df.Filter("nElectron>=2 && nMuon>=2", "At least two electrons and two muons")
22
23
24def define_variables(df):
25 """Define the variables which shall be used for training"""
26 return (
27 df
28 .Define("Muon_pt_1", "Muon_pt[0]")
29 .Define("Muon_pt_2", "Muon_pt[1]")
30 .Define("Electron_pt_1", "Electron_pt[0]")
31 .Define("Electron_pt_2", "Electron_pt[1]")
32 )
33
34
35def prepare_rdf(filename, label_value):
36 """Load, filter, define variables, and add label column"""
37 filepath = "root://eospublic.cern.ch//eos/root-eos/cms_opendata_2012_nanoaod/" + filename
38 df = ROOT.RDataFrame("Events", filepath)
39 df = filter_events(df)
40 df = define_variables(df)
41 df = df.Define("label", f"{label_value}.0")
42 return df
43
44
45def load_data():
46 """Load signal and background data"""
47 rdf_sig = prepare_rdf("SMHiggsToZZTo4L.root", 1)
48 rdf_bkg = prepare_rdf("ZZTo2e2mu.root", 0)
49
50 # Compute class-balancing weights
51 num_sig = rdf_sig.Count().GetValue()
52 num_bkg = rdf_bkg.Count().GetValue()
53 num_all = num_sig + num_bkg
54
55 rdf_sig = rdf_sig.Define("weight", f"{num_all}.0/{num_sig}.0")
56 rdf_bkg = rdf_bkg.Define("weight", f"{num_all}.0/{num_bkg}.0")
57
59 [rdf_sig, rdf_bkg],
60 columns=variables + ["label", "weight"],
61 target="label",
62 weights="weight",
63 batch_size=num_all, # Load all data in one batch
64 drop_remainder=False,
65 set_seed=42,
66 )
67
68 # Split into training and testing sets
69 train, test = loader.train_test_split(test_size=0.5)
70
71 # train.as_numpy() and test.as_numpy() return generators of batches.
72 # Since batch_size=num_all, each split contains exactly one batch;
73 # next(iter(...)) materializes it into in-memory numpy arrays.
74 X_train, y_train, w_train = next(iter(train.as_numpy()))
75 X_test, y_test, w_test = next(iter(test.as_numpy()))
76
77 # Flatten target and weights from (n,1) to (n,) as expected by XGBoost
78 return (X_train, y_train.ravel(), w_train.ravel(), X_test, y_test.ravel(), w_test.ravel())
79
80
81if __name__ == "__main__":
82 from sklearn.metrics import roc_auc_score
83 from xgboost import XGBClassifier
84
85 X_train, y_train, w_train, X_test, y_test, w_test = load_data()
86
87 print(f"Training events: {X_train.shape[0]}")
88 print(f"Testing events: {X_test.shape[0]}")
89
90 bdt = XGBClassifier(max_depth=3, n_estimators=500)
91 bdt.fit(X_train, y_train, sample_weight=w_train)
92
93 # Evaluate on test set
94 y_proba = bdt.predict_proba(X_test)[:, 1]
95 auc = roc_auc_score(y_test, y_proba)
96
97 print(f"Training done. ROC AUC: {auc:.4f}")
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 ,...