Updating to Pytorch 2.4

#5
by chultquist0 - opened
Files changed (43) hide show
  1. .gitattributes +0 -1
  2. README.md +0 -341
  3. physicsnemo/configs/config.yaml +0 -64
  4. physicsnemo/configs/config_stats_all.yaml +0 -65
  5. physicsnemo/configs/tHjb_CP_0_vs_45.yaml +0 -79
  6. physicsnemo/configs/tHjb_CP_0_vs_90.yaml +0 -87
  7. physicsnemo/configs/tHjb_CP_0_vs_90_edge_network.yaml +0 -82
  8. physicsnemo/configs/tHjb_CP_0_vs_90_globals.yaml +0 -84
  9. physicsnemo/dataset/Dataset.py +0 -243
  10. physicsnemo/dataset/GraphBuilder.py +0 -162
  11. physicsnemo/dataset/Graphs.py +0 -88
  12. physicsnemo/dataset/Normalization.py +0 -144
  13. physicsnemo/metrics.py +0 -110
  14. physicsnemo/models/Edge_Network.py +0 -72
  15. physicsnemo/models/MeshGraphNet.py +0 -51
  16. physicsnemo/models/utils.py +0 -135
  17. physicsnemo/setup/Dockerfile +0 -23
  18. physicsnemo/setup/build_image.sh +0 -4
  19. physicsnemo/train.py +0 -246
  20. physicsnemo/utils.py +0 -11
  21. root_gnn_dgl/README.md +34 -49
  22. root_gnn_dgl/configs/attention/ttH_CP_even_vs_odd.yaml +58 -0
  23. root_gnn_dgl/configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml +2 -2
  24. root_gnn_dgl/configs/stats_100K/pretraining_multiclass.yaml +2 -2
  25. root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd.yaml +2 -2
  26. root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_2048.yaml +57 -0
  27. root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_4096.yaml +57 -0
  28. root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_8192.yaml +57 -0
  29. root_gnn_dgl/configs/stats_all/finetuning_ttH_CP_even_vs_odd.yaml +2 -2
  30. root_gnn_dgl/configs/stats_all/pretraining_multiclass.yaml +2 -2
  31. root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd.yaml +2 -2
  32. root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_2048.yaml +57 -0
  33. root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_4096.yaml +57 -0
  34. root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_8192.yaml +57 -0
  35. root_gnn_dgl/jobs/interactive.sh +1 -1
  36. root_gnn_dgl/run_demo.sh +3 -3
  37. root_gnn_dgl/scripts/inference.py +32 -48
  38. root_gnn_dgl/setup/Dockerfile +8 -5
  39. root_gnn_dgl/setup/build_image.sh +4 -2
  40. root_gnn_dgl/setup/environment.yml +3 -2
  41. root_gnn_dgl/setup/environment_torch24.yaml +249 -0
  42. root_gnn_dgl/setup/launch_image.sh +0 -9
  43. training_time.png +0 -3
.gitattributes CHANGED
@@ -33,4 +33,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
- training_time.png filter=lfs diff=lfs merge=lfs -text
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
README.md CHANGED
@@ -1,344 +1,3 @@
1
  ---
2
  license: mit
3
  ---
4
- ## Abstract
5
-
6
- We introduce a foundation model for event classification in high-energy physics, built on a **Graph Neural Network** architecture and trained on **120 million simulated proton-proton collision events** spanning 12 distinct physics processes. The model is *pretrained* to learn a general and robust representation of collision data using challenging multiclass and multilabel classification tasks.
7
-
8
- Its performance is evaluated across five event classification tasks, which include both physics processes used during pretraining and new processes not encountered during pretraining. Fine-tuning the pretrained model significantly improves classification performance, particularly in scenarios with limited training data, demonstrating gains in both accuracy and computational efficiency.
9
-
10
- To investigate the underlying mechanisms behind these performance improvements, we employ a representational similarity evaluation framework based on *Centered Kernel Alignment*. This analysis reveals notable differences in the learned representations of fine-tuned pretrained models compared to baseline models trained from scratch.
11
-
12
- ## Introduction
13
-
14
- Machine learning has become a ubiquitous tool in particle physics, employed in a variety of tasks including triggering, simulation, reconstruction, and offline analysis. While its utility spans classification, regression, and generative tasks, the current paradigm of developing machine learning models from scratch for each specific application presents several challenges. This approach not only demands specialized expertise and substantial computing resources but can also result in suboptimal performance due to limited training data. The from-scratch development of models necessitates individual validation studies to ensure that neural networks utilize well-modeled information from training samples, whether derived from Monte Carlo simulations or control samples from experimental data.
15
-
16
- Foundation models offer a promising direction to address these limitations. These models, pre-trained on large, diverse datasets across various tasks, provide robust and general representations of underlying data structures. Notable examples in other fields include GPT-4 [OpenAI et al., 2024](#ref-openai-2024-gpt4) and BERT [Devlin et al., 2018](#ref-devlin-2018-bert) in natural language processing, Stable Diffusion [Rombach et al., 2021](#ref-rombach-2021-latentdiffusion) in image processing, and AlphaFold [Jumper et al., 2021](#ref-jumper-2021-alphafold) in structural biology. The foundation model approach offers several advantages for particle physics applications: reduced computing resources for fine-tuning [Yosinski et al., 2014](#ref-yosinski-2014-transfer) compared to training from scratch, superior performance on specific tasks (particularly with limited training data), and potentially simplified validation procedures as downstream tasks inherit verified representations from the pre-trained model.
17
-
18
- Current literature on pretrained models for particle physics can be categorized based on the data representation they handle. Models operating on particle- or event-level numerical data use features like particle four momenta or jets, leveraging self-supervised or generative methods to learn versatile representations. Detector-focused models operate on high-dimensional responses such as calorimeter deposits or pixel hits, employing geometry-aware techniques for accurate simulation and analysis. Finally, models using textual or code representations apply large language model architectures to integrate domain knowledge, enabling tasks like question answering and code generation.
19
-
20
- Recent studies have begun exploring foundation models tailored to particle physics data, which has a variety of distinct structures and properties across many experiments and data processing stages, including:
21
-
22
- - particle-level & event-level numeric data [Wildridge et al., 2024](#ref-wildridge-2024-bumblebee), [Katel et al., 2024](#ref-katel-2024-jet), [Golling et al., 2024](#ref-golling-2024-maskedset), [Mikuni & Nachman, 2024](#ref-mikuni-2024-omnilearn), [Harris et al., 2024](#ref-harris-2024-resimulation), [Birk et al., 2024](#ref-birk-2024-omnijet), [Vigl et al., 2024](#ref-vigl-2024-finetune),
23
- - detector-level & geometry-aware data [Araz et al., 2024](#ref-araz-2024-pointcloud), [Liu et al., 2023](#ref-liu-2023-gaam), [Hashemi et al., 2024](#ref-hashemi-2024-gen), [Huang et al., 2024](#ref-huang-2024-lmtracking),
24
- - textual or code data [Zhang et al., 2024](#ref-zhang-2024-xiwu).
25
-
26
- This paper presents a foundation model designed specifically for collider event-level data. In modern collider experiments, final-stage analysis processes information from reconstructed objects that either directly correspond to particles in collision final states (such as leptons and photons) or serve as proxies (such as jets and missing transverse energy). While traditional approaches often relied on "high-level" variables calculated from object features, recent trends favor direct input of event objects and their features into neural networks for analysis tasks. A notable example is [ATLAS Collaboration, 2023](#ref-atlas-2023-4top), which established the observation of simultaneous production of four top quarks with the ATLAS experiment by employing a graph neural network (GNN) architecture to process event-level object information.
27
-
28
- We present foundation models that adopt an architecture similar to that used for [ATLAS Collaboration, 2023](#ref-atlas-2023-4top). Our models are pre-trained using either multiclass classification or multi-label learning tasks across 12 distinct physics processes. We evaluate these models through fine-tuning and testing on five classification tasks, including both familiar and novel processes not seen during pre-training. Our analysis benchmarks the models' performance improvements, their scaling behavior with training sample size, and computational efficiency, representing the first prototype of a foundation model operating on collider final-state object data.
29
-
30
- ## Data Samples
31
-
32
- To provide a diverse set of physics processes for the pretraining, we use Madgraph@NLO 2.7.3 [Alwall et al., 2014](#ref-alwall-2014hca) to generate proton-proton collision events at next-to-leading order (NLO) in Quantum Chromodynamics (QCD). We generate 12 distinct Standard Model (SM) physics processes, including six major Higgs boson production mechanisms: gluon fusion production \\(ggF\\), vector boson fusion \\(VBF\\), associated production of the Higgs boson with a W boson \\(WH\\) or a Z boson \\(ZH\\), associated production of the Higgs boson with a top-quark pair \\(t\bar{t}H\\), and associated production of the Higgs boson with a single top quark and a forward quark \\(tHq\\). Additionally, we simulate six top quark production processes: single top production, top-quark pair production \\(t\bar{t}\\), top quark pair production in association with a pair of photons \\(t\bar{t}\gamma\gamma\\), associated production of a top-quark pair with a W boson \\(t\bar{t}W\\), simultaneous production of three top quarks \\(t\bar{t}t\\), and simultaneous production of four top quarks \\(t\bar{t}t\bar{t}\\). In these samples, the Higgs boson and top quarks decay inclusively. These 12 Higgs and top quark production processes constitute the pretraining dataset.
33
-
34
- To test the pretrained model, we further generated four processes including three beyond Standard Model (SM) processes: a SM \\(t\bar{t}H\\) production where the Higgs boson decays exclusively to a pair of photons, a \\(t\bar{t}H\\) production with the Higgs boson decaying to a pair of photons, where the top-Yukawa coupling is CP-odd, implemented using the Higgs Characterization model [Artoisenet et al., 2013](#ref-artoisinet-2013puc), the production of a pair of superpartners of the top quark (s-top) using the Minimal Supersymmetric Standard Model (MSSM) [Rosiek, 1990](#ref-rosiek-1990), [Allanach et al., 2009](#ref-allanach-2009), and flavor changing neutral current (FCNC) processes [Degrande et al., 2015](#ref-degrande-2015), [Durieux et al., 2015](#ref-durieux-2015). For the s-top process, we simulate the production of heavier s-top pairs \\(t_2\bar{t_2}\\), where each heavier s-top (mass 582 GeV) decays into a lighter s-top \\(t_1\\) or \\(\bar{t_1}\\), mass 400 GeV) and a Higgs boson. The FCNC process involves \\(t\bar{t}\\) production where one top quark decays to a Higgs boson and a light quark. We generate 10 million events for each process, except for \\(tHq\\) and \\(t\bar{t}t\bar{t}\\), where 5 million events were produced.
35
-
36
- In all simulation samples, the center of mass energy of the proton-proton collision is set to 13 TeV. The Higgs boson, top quarks, and vector bosons are set to decay inclusively (except the \\(t\bar{t}H \rightarrow \gamma\gamma\\) samples), with MadSpin [Artoisenet et al., 2012](#ref-artoisinet-2012st) handling the decays of top quarks and W bosons. The generated events are processed through Pythia 8.235 [Sjostrand et al., 2015](#ref-sjostrand-2015) for parton showering and heavy particle decays, followed by Delphes 3.4.2 [de Favereau et al., 2014](#ref-defavereau-2014) configured to emulate the ATLAS detector [ATLAS Collaboration, 2008](#ref-atlas-2008) for fast detector simulation.
37
-
38
- The detector-level object selection criteria are defined to align with typical experimental conditions. Photons are required to have transverse momentum \\(p_T \geq 20~\mathrm{GeV}\\) and pseudorapidity \\(|\eta| \leq 2.37\\), excluding the electromagnetic calorimeter crack region \\(1.37 < |\eta| < 1.52\\). Electrons must have \\(p_T \geq 10~\mathrm{GeV}\\) and \\(|\eta| \leq 2.47\\) (excluding the same crack region), while muons are selected with \\(p_T \geq 10~\mathrm{GeV}\\) and \\(|\eta| \leq 2.7\\). Jets are reconstructed using the anti-\\(k_t\\) algorithm [Cacciari et al., 2008](#ref-cacciari-2008gp) with radius parameter \\(\Delta R=0.4\\), where \\(\Delta R\\) is defined as \\(\sqrt{\Delta\eta ^2 + \Delta\phi^2}\\), with \\(\Delta\eta\\) being the difference in pseudorapidity and \\(\Delta\phi\\) the difference in azimuthal angle. Jets must satisfy \\(p_T \geq 25~\mathrm{GeV}\\) and \\(|\eta| \leq 2.5\\). To avoid double-counting, jets are removed if they are within \\(\Delta R < 0.4\\) of a photon or lepton. The identification of jets originating from b-quark decays (b-tagging) is performed by matching jets within \\(\Delta R = 0.4\\) of a b-quark, with efficiency corrections applied to match the performance of the ATLAS experiment's b-tagging algorithm [ATLAS Collaboration, 2019](#ref-atlas-2019bwq).
39
-
40
- ## Methods
41
-
42
- ### Overview
43
-
44
- We present a methodology for developing and evaluating a foundation model for particle collision event analysis. The approach centers on pretraining a Graph Neural Network (GNN) architecture using a comprehensive dataset that spans multiple physics tasks, enabling the model to learn robust and transferable features. For task-specific applications, we employ a fine-tuning strategy that combines output layer adaptation with carefully calibrated learning rates for updating the pretrained parameters.
45
-
46
- Given the prevalence of classification problems in particle physics data analysis, we evaluate the model's efficacy through a systematic assessment across five binary classification tasks:
47
-
48
- - \\(t\bar{t}H(\rightarrow \gamma\gamma)\\) with CP-even versus CP-odd t-H interaction
49
- - \\(t\bar{t}\\) with FCNC top quark decays versus $tHq$ processes
50
- - \\(t\bar{t}W\\) versus $ttt$ processes
51
- - Stop pair production with Higgs bosons in the decay chain versus \\(t\bar{t}H\\) processes
52
- - \\(WH\\) versus \\(ZH\\) production modes
53
-
54
- Our evaluation metrics encompass classification performance, computational efficiency, and model interpretability. The investigation extends to analyzing the model's scaling behavior with respect to training dataset size, benchmarked against models trained without pretraining. Although we explored transfer learning through parameter freezing of pretrained layers, this approach did not yield performance improvements, leading us to focus our detailed analysis on fine-tuning strategies.
55
-
56
- This methodological framework demonstrates the potential of foundation models to enhance the efficiency of particle physics analyses while improving task-specific performance, offering a promising direction for future high-energy physics research.
57
-
58
- ---
59
-
60
- ### GNN Architecture
61
-
62
- We implement a Graph Neural Network (GNN) architecture that naturally accommodates the point-cloud structure of particle physics data, employing the DGL framework with a PyTorch backend [Wang et al., 2019][ref-dgl-2019], [Paszke et al., 2019][ref-pytorch-2019]. A fully connected graph is constructed for each event, with nodes corresponding to reconstructed jets, electrons, muons, photons, and \\(\vec{E}_T^{\text{miss}}\\). The features of each node include the four-momentum \\((p_T, \eta, \phi, E)\\) of the object with a massless assumption (\\(E = p_T \cosh \eta\\)), the b-tagging label (for jets), the charge (for leptons), and an integer labeling the type of object represented by the node. We use a placeholder value of 0 for features which are not defined for every node type such as the b-jet tag, lepton charge, or the pseudorapidity of \\(\vec{E}_T^{\text{miss}}\\). We assign the angular distances (\\(\Delta \eta, \Delta \phi, \Delta R\\)) as edge features and the number of nodes $N$ in the graph as a global feature. We denote the node features \\(\{\vec x_i\}\\), edge features \\(\{\vec y_{ij}\}\\), and global features \\(\{\vec z\}\\).
63
-
64
- The GNN model is based on the graph network architecture described in [Battaglia et al., 2018][ref-graphnets-2018] using simple multilayer perceptron (MLP) feature functions and summation aggregation. The model is comprised of three primary components: an encoder, the graph network, and a decoder. In the encoder, three MLPs embed the nodes, edges, and global features into a latent space of dimension 64. The graph network block, which is designed to facilitate message passing between different domains of the graph, performs an edge update $f_e$, followed by a node update $f_n$, and finally a global update $f_g$, all defined below. The inputs to each update MLP are concatenated.
65
-
66
- $$
67
- \vec {y'}_{ij} = f_e\left(\{\vec x_k\},\vec y_{ij},\vec z\right) = \mathrm{MLP}\left(\vec x_i,\vec x_j,\vec y_{ij},\vec z\right)
68
- $$
69
-
70
- $$
71
- \vec{x'}_{i} = f_n\left(\vec x_i,\{\vec{y'}_{jk}\},\vec z\right) = \mathrm{MLP}\left(\vec x_i,\sum_j\vec{y'}_{ij},\vec z\right)
72
- $$
73
-
74
- $$
75
- \vec{z'} = f_g\left(\{\vec{x'}_i\},\{\vec{y'}_{ij}\},\vec z\right) = \mathrm{MLP}\left(\sum_i\vec{x'}_i,\sum_{i,j}\vec{y'}_{ij},\vec z\right)
76
- $$
77
-
78
- This graph block is iterated four times with the same update MLPs. Finally, the global features are passed through a decoder MLP and a final layer linear to produce the desired model outputs. Each MLP consists of 4 linear layers, each with an output width of 64, with the `ReLU` activation function. The output of the MLP is then passed through a `LayerNorm` layer [Ba et al., 2016][ref-layernorm-2016]. The total number of trainable parameters in this model is about 400,000.
79
-
80
- As a performance benchmark, a baseline GNN model is trained from scratch for each classification task. The initial learning rate is set to \\(10^{-4}\\) with an exponential decay following \\(LR(x) = LR_{\text{initial}}\cdot(0.99)^x\\), where \\(x\\) represents the epoch number.
81
-
82
- ---
83
-
84
- ### Pretraining Strategy
85
-
86
- We explore two complementary pretraining approaches to develop robust representations of collision events: (1) multi-class classification, which trains the model to distinguish between different physics processes, and (2) multi-label classification, which predicts the existence and kinematics of heavy particles with prompt decays. The pretraining dataset consists of approximately 120 million events, evenly distributed across 12 distinct physics processes, including all major Higgs boson production mechanisms and top quark processes as described in [Data Samples](#sec-data). This large-scale pretraining effort was conducted on the Perlmutter supercomputer at NERSC.
87
-
88
- #### Multi-class Classification
89
-
90
- For Monte Carlo simulated events, the underlying physics process that generated each event is known precisely, providing natural labels for supervised learning. However, the challenge lies in the complexity of collision events: different physics processes can produce similar kinematics and event topologies, particularly in certain regions of phase space. No single observable can unambiguously identify the underlying process. By training the model to distinguish between 12 different processes simultaneously, we challenge it to learn subtle differences in kinematics and topology that collectively characterize each process. The model is trained using categorical cross entropy as the loss function. The output layer of the multiclass classification model has 832 trainable parameters.
91
-
92
- #### Multi-label Classification
93
-
94
- This approach combines both classification and regression tasks to characterize collision events. For discrete properties like particle presence in specific kinematic regions, we employ classification labels with binary cross-entropy loss. For continuous quantities like particle multiplicities, we use regression labels with mean-squared error loss. This hybrid approach enables the model to learn both categorical and continuous aspects of the physics processes simultaneously.
95
-
96
- We develop a comprehensive set of 41 labels that capture both particle multiplicities and kinematic properties. This approach increases prediction granularity and enhances model interpretability. By training the model to predict event kinematics rather than event identification, we create a task-independent framework that can potentially generalize better to novel scenarios not seen during pretraining.
97
-
98
- The particle multiplicity labels count the number of Higgs bosons (\\(n_{\text{higgs}}\\)), top quarks (\\(n_{\text{tops}}\\)), vector bosons (\\(n_V\\)), \\(W\\) bosons (\\(n_W\\)), and \\(Z\\) bosons (\\(n_Z\\)). The kinematic labels characterize the transverse momentum (\\(p_T\\)), pseudorapidity (\\(\eta\\)), and azimuthal angle (\\(\phi\\)) of Higgs bosons and top quarks through binned classifications.
99
-
100
- For Higgs bosons, $p_T$ is categorized into three ranges: (0, 30) GeV, (30, 200) GeV, and (200, \\(\infty\\)) GeV, with the upper range particularly sensitive to potential BSM effects. Similarly, both leading and subleading top quarks have $p_T$ classifications spanning (0, 30) GeV, (30, 300) GeV, and (300, \\(\infty\\)) GeV. When no particle exists within a specific \\(p_T\\) range, the corresponding label is set to \\([0, 0, 0]\\). For all particles, \\(\eta\\) measurements are divided into 4 bins with boundaries at \\([-1.5, 0, 1.5]\\), while \\(\phi\\) measurements use 4 bins with boundaries at \\([-\frac{\pi}{2}, 0, \frac{\pi}{2}]\\). As with \\(p_T\\), both \\(\eta\\) and \\(\phi\\) labels default to \\([0, 0, 0, 0]\\) in the absence of a particle. This comprehensive labeling schema enables fine-grained learning of kinematic distributions and particle multiplicities, essential for characterizing complex collision events.
101
-
102
- The loss function combines individual losses from all 41 labels through weighted averaging. Binary cross-entropy is applied to classification labels, while mean-squared error is used for regression labels. The model generates predictions for all labels simultaneously, with individual losses calculated according to their respective types. The final loss is computed as an equally-weighted average across all labels, with weights set to 1 to ensure uniform contribution to the optimization process. The output layer of the multilabel model has 2,688 trainable parameters.
103
-
104
- #### Pretraining
105
-
106
- During pre-training, the initial learning rate is \\(10^{-4}\\), and the learning rate decays by 1% each epoch following the power law function \\(LR(x) = 10^{-4}\cdot(0.99)^x\\), where \\(x\\) is the number of epochs. Both pre-trained models reach a plateau in loss by epoch 50, at which point the training is stopped.
107
-
108
- ---
109
- ### Fine-tuning Methodology
110
-
111
- For downstream tasks, we adjust the model architecture for fine-tuning by replacing the original output layer (final linear layer) with a newly initialized linear layer while retaining the pre-trained weights for all other layers. This modification allows the model to specialize in the specific downstream task while leveraging the general features learned during pretraining.
112
-
113
- The fine-tuning process begins with distinct learning rate setups for different parts of the model. The newly initialized linear layer is trained with an initial learning rate of \\(10^{-4}\\), matching the rate used for models trained from scratch. Meanwhile, the pre-trained layers are fine-tuned more cautiously with a lower initial learning rate of \\(10^{-5}\\). This approach ensures that the pre-trained layers adapt gradually without losing their general features, while the new layer learns effectively from scratch. Both learning rates decay over time following the same power law function, \\(LR(x) = LR_{initial} \cdot (0.99)^x\\), to promote stable convergence as training progresses.
114
-
115
- We also evaluated a transfer learning setup in which either the decoder MLP or the final linear layer was replaced with a newly initialized component. During this process, all other model parameters remained frozen, leveraging the pre-trained features without further updating them. However, we did not observe performance improvements using the transfer learning setup. Consequently, we focus on reporting results obtained with the fine-tuning approach.
116
-
117
- ---
118
-
119
- ### Performance Evaluation
120
-
121
- We assess model performance using two figures of merit: the classification accuracy and the Area Under the Curve (AUC) of the Receiver Operating Characteristic (ROC) curve. The accuracy is defined as the fraction of correctly classified events when applying a threshold of 0.5 to the neural network output score. Both metrics demonstrate consistent trends in our analysis.
122
-
123
- To obtain reliable performance estimates and uncertainties, we employ an ensemble training approach where 5 independent models are trained for each configuration with random weight initialization and random subsets of the training dataset. This enables us to evaluate both the models' sensitivity to initial parameters and to quantify uncertainties in their performance.
124
-
125
- To investigate how model performance scales with training data, we conducted training runs using sample sizes ranging from \\(10^3\\) to \\(10^7\\) events per class (\\(10^3\\), \\(10^4\\), \\(10^5\\), \\(10^6\\), and \\(10^7\\)) for each model setup: the from-scratch baseline and models fine-tuned from multi-class or multi-label pretrained models. For the \\(10^7\\) case, only the initialization was randomized due to dataset size limitations. All models were evaluated on the same testing dataset, consisting of 2 million events per class, which remained separate from the training process.
126
-
127
- | **Name of Task** | **Pretraining Task** | \\(10^3\\) | \\(10^4\\) | \\(10^5\\) | \\(10^6\\) | \\(10^7\\) |
128
- |----------------------|----------------------|--------------------|--------------------|--------------------|--------------------|--------------------|
129
- | **ttH CP Even vs Odd** | Baseline Accuracy | 56.5 ± 1.1 | 62.2 ± 0.1 | 64.3 ± 0.0 | 65.7 ± 0.0 | 66.2 ± 0.0 |
130
- | | Multiclass (%) | +4.8 ± 1.1 | +3.4 ± 0.1 | +1.3 ± 0.0 | +0.2 ± 0.0 | −0.0 ± 0.0 |
131
- | | Multilabel (%) | +2.1 ± 1.2 | +1.9 ± 0.1 | +0.8 ± 0.1 | +0.0 ± 0.0 | −0.1 ± 0.0 |
132
- | **FCNC vs tHq** | Baseline Accuracy | 63.6 ± 0.7 | 67.8 ± 0.4 | 68.4 ± 0.3 | 69.3 ± 0.3 | 67.9 ± 0.0 |
133
- | | Multiclass (%) | +5.8 ± 0.8 | +1.2 ± 0.4 | +1.4 ± 0.3 | +0.5 ± 0.3 | −0.0 ± 0.0 |
134
- | | Multilabel (%) | −5.3 ± 0.8 | −1.3 ± 0.4 | +0.9 ± 0.4 | +0.3 ± 0.3 | +0.4 ± 0.1 |
135
- | **ttW vs ttt** | Baseline Accuracy | 75.8 ± 0.1 | 77.6 ± 0.1 | 78.9 ± 0.0 | 79.8 ± 0.0 | 80.3 ± 0.0 |
136
- | | Multiclass (%) | +3.7 ± 0.1 | +2.7 ± 0.1 | +1.3 ± 0.0 | +0.4 ± 0.0 | +0.0 ± 0.0 |
137
- | | Multilabel (%) | +2.2 ± 0.1 | +1.1 ± 0.1 | +0.5 ± 0.0 | +0.0 ± 0.0 | −0.1 ± 0.0 |
138
- | **stop vs ttH** | Baseline Accuracy | 83.0 ± 0.2 | 86.3 ± 0.1 | 87.6 ± 0.0 | 88.5 ± 0.0 | 88.8 ± 0.0 |
139
- | | Multiclass (%) | +0.4 ± 0.2 | +1.9 ± 0.1 | +1.0 ± 0.0 | +0.3 ± 0.0 | +0.0 ± 0.0 |
140
- | | Multilabel (%) | +2.8 ± 0.2 | +1.0 ± 0.1 | +0.5 ± 0.0 | +0.0 ± 0.0 | −0.0 ± 0.0 |
141
- | **WH vs ZH** | Baseline Accuracy | 51.4 ± 0.1 | 53.9 ± 0.1 | 55.8 ± 0.0 | 57.5 ± 0.0 | 58.0 ± 0.0 |
142
- | | Multiclass (%) | +5.2 ± 0.1 | +5.3 ± 0.1 | +3.1 ± 0.0 | +0.6 ± 0.0 | +0.1 ± 0.0 |
143
- | | Multilabel (%) | −1.1 ± 0.1 | −0.9 ± 0.2 | +0.5 ± 0.1 | +0.1 ± 0.0 | −0.1 ± 0.0 |
144
-
145
- > **Table 1**: Accuracy of the traditional model versus the accuracy increase due to fine-tuning from various pretraining tasks.
146
- > The accuracies are averaged over 5 independently trained models with randomly initialized weights and trained on a random subset of the data. One exception is the \\(10^7\\) training where all models use the same dataset due to limitations on our dataset size. The random subsets are allowed to overlap, but this overlap should be very minimal because all models take an independent random subset of \\(10^7\\) events. The testing accuracy is calculated from the same testing set of 2 million events per class across all models for a specific training task. The errors are the propagated errors (root sum of squares) of the standard deviation of accuracies for each model.
147
-
148
- ## Results
149
-
150
- ### Classification Performance
151
-
152
- Since the observations of AUC and accuracy show similar trends, we focus the presentation of the results using accuracy here for conciseness in Table 1.
153
-
154
- In general, the fine-tuned pretrained model achieves at least the same level of classification performance as the baseline model. Notably, there are significant improvements, particularly when the sample size is small, ranging from \\(10^3\\) to \\(10^4\\) events. In some cases, the accuracy improvements exceed five percentage points, demonstrating that pretrained models provide a strong initial representation that compensates for limited data. The numerical values of the improvements in accuracy may not fully capture the impact on the sensitivity of the measurements for which the neural network classifier is used, and the final sensitivity improvement is likely to be greater.
155
-
156
- As the training sample size grows to \\(10^5\\), \\(10^6\\), and eventually \\(10^7\\) events, the added benefit of pretraining diminishes. With abundant data, models trained from scratch approach or even match the accuracy of fine-tuned pretrained models. This suggests that large datasets enable effective learning from scratch, rendering the advantage of pretraining negligible in such scenarios.
157
-
158
- Although both pretraining approaches offer benefits, multiclass pretraining tends to provide more consistent improvements across tasks, especially in the low-data regime. In contrast, multilabel pretraining can sometimes lead to neutral or even slightly negative effects for certain tasks and data sizes. This highlights the importance of the pretraining task design, as the similarity between pretraining and fine-tuning tasks in the multiclass approach appears to yield better-aligned representations.
159
-
160
- Finally, the spread of accuracy across the five tasks for the baseline model is quite large, offering a robust test of fine-tuning across tasks of varying difficulty. The consistent observation of these trends across tasks confirms the reliability and robustness of the findings.
161
-
162
- ---
163
-
164
- ### Model Interpretability
165
-
166
- We aim to understand whether pretrained and baseline models learn the same underlying representations. If the two models exhibit high similarity, a plausible interpretation is that pretraining provides the pretrained model with an advantageous initialization, allowing it to converge to a similar state as the baseline model more efficiently. Conversely, significant differences between the models would indicate that pretraining facilitates the development of a more general and robust latent space, which serves as a foundation for fine-tuning to effectively adapt to the downstream task. To investigate this, we analyzed the representational similarity between a pretrained model fine-tuned for the downstream task and a baseline model trained directly on the downstream task without pretraining.
167
-
168
- We use Centered Kernel Alignment (CKA) [Kornblith et al., 2019][ref-kornblith-2019-cka] to analyze model similarity and interpretability. CKA is a robust metric that quantifies the similarity between the internal representations of neural networks by comparing their feature matrices in a manner that is invariant to scaling, rotation, and alignment. This invariance makes CKA particularly effective for studying relationships between network layers, even across networks of different sizes or those trained from varying initializations.
169
-
170
- The similarity is evaluated using a 64-dimensional latent representation after the decoder stage of the GNN model. This choice allows us to compare the internal states of the models at a fine-grained level and understand how training strategies impact the representations directly used for the output task.
171
-
172
- To provide an intuitive understanding of CKA values, we construct a table of the CKA scores for various transformations performed on a set of dummy data.
173
-
174
- - **A:** randomly initialized matrix with shape (1000, 64), following a normal distribution (\\(\sigma = 1, \mu = 0\\))
175
- - **B:** matrix with shape (1000, 64) constructed via various transformations performed on \\(A\\)
176
- - **Noise:** randomly initialized noise matrix with shape (1000, 64), following a normal distribution (\\(\sigma = 1, \mu = 0\\))
177
-
178
- | Dataset | CKA Score |
179
- |---------|-----------|
180
- | \\(A, B = A\\) | 1.00 |
181
- | \\(A, B =\\) permutation on columns of \\(A\\) | 1.00 |
182
- | \\(A, B = A + \mathrm{Noise}(0.1)\\) | 0.99 |
183
- | \\(A, B = A + \mathrm{Noise}(0.5)\\) | 0.80 |
184
- | \\(A, B = A + \mathrm{Noise}(0.75)\\) | 0.77 |
185
- | \\(A, B = A \cdot \mathrm{Noise}(1)\\) (Linear Transformation) | 0.76 |
186
- | \\(A, B = A + \mathrm{Noise}(1)\\) | 0.69 |
187
- | \\(A, B = A + \mathrm{Noise}(2)\\) | 0.51 |
188
- | \\(A, B = A + \mathrm{Noise}(5)\\) | 0.39 |
189
-
190
- **Table 2:** CKA scores for a dummy dataset \\(A\\) and \\(B\\), where \\(B\\) is created via various transformations performed on \\(A\\).
191
-
192
- As seen in Table 2 and in the definition of the CKA, the CKA score is permutation-invariant. We will use the CKA score to evaluate the similarity between various models and gain insight into the learned representation of detector events in each model (i.e., the information that each model learns).
193
-
194
- We train ensembles of models for each training task to observe how the CKA score changes due to the random initialization of our models. The CKA score between two models is then defined to be:
195
-
196
- \\[
197
- CKA(A, B) = \frac{1}{n^2} \sum_i^n \sum_j^n CKA(A_i, B_j)
198
- \\]
199
-
200
- where \\(A_i\\) is the representation learned by the \\(i^{\text{th}}\\) model in an ensemble with \\(n\\) total models. The error in CKA is the standard deviation of \\(CKA(A_i, B_j)\\).
201
-
202
- Here we present results for the CKA similarity between the final model in each setup with the final model in the baseline, shown in Table 3.
203
-
204
- | Training Task | Baseline | Multiclass | Multilabel |
205
- |-----------------------|------------------|-----------------|-----------------|
206
- | ttH CP Even vs Odd | 0.94 ± 0.05 | 0.82 ± 0.01 | 0.77 ± 0.06 |
207
- | FCNC vs tHq | 0.96 ± 0.03 | 0.76 ± 0.01 | 0.81 ± 0.01 |
208
- | ttW vs ttt | 0.91 ± 0.08 | 0.75 ± 0.10 | 0.72 ± 0.05 |
209
- | stop vs ttH | 0.87 ± 0.11 | 0.79 ± 0.12 | 0.71 ± 0.08 |
210
- | WH vs ZH | 0.90 ± 0.07 | 0.53 ± 0.03 | 0.44 ± 0.06 |
211
-
212
- **Table 3:** CKA Similarity of the latent representation before the decoder with the baseline model, averaged over 3 models per training setup, and all models trained with the full dataset (\\(10^7\\)). The baseline column is not guaranteed to be 1.0 because of the random initialization of the model. Each baseline model converges to a slightly different representation as seen in the CKA values in that column.
213
-
214
- The baseline models with different initializations exhibit high similarity values, ranging from approximately 0.87 to 0.96, which indicates that independently trained baseline models tend to converge on similar internal representations despite random initialization. Across the considered tasks, models trained as multi-class or multi-label classifiers exhibit noticeably lower CKA similarity scores when compared to the baseline model. For example, in the WH vs ZH task, the baseline model and another baseline trained model have a high similarity of 0.90, whereas the multi-class and multi-label models show significantly reduced similarities (0.53 and 0.44, respectively). This pattern suggests that the representational spaces developed by multi-class or multi-label models differ substantially from those learned by the baseline model that was trained directly on the downstream classification task.
215
-
216
- ### Computational Efficiency
217
-
218
- To estimate the computational resources required for each approach, we measured the wall time needed for a model to reach its final performance. For baseline models, this is defined as the wall time from the start of training until the loss of the model plateaus. For the foundation model approach, the estimate includes both the pretraining time and the fine-tuning time, each measured from the start of training until the loss plateaus. This approach ensures a consistent and comprehensive evaluation of the computational demands.
219
-
220
- ![The ratio of the fine-tuning time required to achieve 99% of the baseline model's final classification accuracy to the total time spent training the baseline model.](training_time.png)
221
- *Fig. 1: The ratio of the fine-tuning time required to achieve 99% of the baseline model's final classification accuracy to the total time spent training the baseline model.*
222
-
223
- Figure 1 shows the fine-tuning time for the model pretrained with multiclass classification, relative to the time required for the baseline model, as a function of training sample size. In general, the fine-tuning time is significantly shorter than the training time required by the baseline model approach. For smaller training sets, on the order of \\(10^5\\) events, tasks such as FCNC vs. tHq and ttW vs. ttt benefit substantially from the pretrained model’s “head start,” achieving their final performance in only about 1% of the baseline time. For large training datasets, the fine-tuning time relative to the baseline training time becomes larger; however, given that the large training sample typically requires longer training time, fine-tuning still yields much faster training convergence. The ttH CP-even vs. ttH CP-odd task, with a training sample size of \\(10^7\\) events, is an exception where the fine-tuning time exceeds the training time required for the baseline model. This is likely because the processes involved in this task include photon objects in the final states, which are absent from the events used during pretraining.
224
-
225
- To accurately evaluate the total time consumption, it is necessary to include the pretraining time required for the foundation model approach. The pretraining times are as follows:
226
-
227
- - **Multi-class pretraining:** 45.5 GPU hours
228
- - **Multi-label pretraining:** 60.0 GPU hours
229
-
230
- The GPU hours recorded for the multi-label model represent the total time required when training the model in parallel on 16 GPUs. This includes a model synchronization step, which results in higher GPU hours compared to the multi-class pretraining model.
231
-
232
- The foundation model approach becomes increasingly efficient when a large number of tasks are fine-tuned using the same pretrained model, compared to training each task independently from scratch. To illustrate this, we evaluate the computational time required for a scenario where the training sample contains \\(10^7\\) events. For the five tasks tested in this study, the baseline training time (training from scratch) ranges from 1.68 GPU hours (WH vs. ZH) to 5.30 GPU hours (ttW vs. ttt), with an average baseline training time of 2.94 GPU hours. In contrast, the average fine-tuning time for the foundation model approach, relative to the baseline, is 38% of the baseline training time for \\(10^7\\) events. Based on these averages, we estimate that the foundation model approach becomes more computationally efficient than the baseline approach when fine-tuning is performed for more than 41 tasks.
233
-
234
- As a practical example, the ATLAS measurement of Higgs boson couplings using the \\(H \rightarrow \gamma\gamma\\) decay channel [ATLAS Collaboration, 2023][ref-atlas-2023-higg] involved training 42 classifiers for event categorization. This coincides with our estimate, suggesting that the foundation model approach can reduce computational costs even for a single high-energy physics measurement.
235
-
236
- ## Conclusions
237
-
238
- We presented an in-depth study of a particle physics foundation model designed to operate on the four-momentum and identification properties of event final-state objects. This model is built on a Graph Neural Network (GNN) architecture and trained on a dataset comprising 120 million simulated proton-proton collision events across 12 distinct physics processes. The pretraining phase explored both multiclass and multilabel classification tasks, providing a robust foundation for downstream applications. Notably, the pretrained models demonstrated significant improvements in event classification performance when fine-tuned, particularly for tasks with limited training samples.
239
-
240
- The foundation model approach also offers substantial computational advantages. By leveraging fine-tuning, this methodology reduces the computational resources required for large-scale applications across multiple tasks. Our estimates indicate that significant resource savings can be achieved even for single particle physics measurements, making this approach both scalable and efficient.
241
-
242
- To better understand the learned representations of the pretrained model and guide future optimization efforts, we employed a representational similarity evaluation framework using Centered Kernel Alignment (CKA). This metric allowed us to investigate the source of the performance gains observed in the foundation model. Our analysis revealed notable differences in the learned representations between the fine-tuned pretrained model and a baseline model trained from scratch. In deep learning, it is well-established that multiple equally valid solutions can exist. Future studies are necessary to determine whether the low similarity in latent representations reflects complementary information uniquely captured by the foundation and baseline models, or if it can simply be attributed to connected local minima in the loss landscape.
243
-
244
- ## Acknowledgments
245
-
246
- This work is supported by the U.S. National Science Foundation under the Award No. 2046280, and by U.S. Department of Energy, Office of Science under contract DE-AC02-05CH11231.
247
-
248
- ## References
249
-
250
- - <span id="ref-openai-2024-gpt4"></span> **OpenAI et al.** GPT-4 Technical Report. arXiv:2303.08774 (2024). [https://arxiv.org/abs/2303.08774](https://arxiv.org/abs/2303.08774)
251
-
252
- - <span id="ref-yosinski-2014-transfer"></span> **Jason Yosinski, Jeff Clune, Yoshua Bengio, Hod Lipson.** How transferable are features in deep neural networks? CoRR abs/1411.1792 (2014). [http://arxiv.org/abs/1411.1792](http://arxiv.org/abs/1411.1792)
253
-
254
- - <span id="ref-rombach-2021-latentdiffusion"></span> **Robin Rombach, Andreas Blattmann, Dominik Lorenz, Patrick Esser, Björn Ommer.** High-Resolution Image Synthesis with Latent Diffusion Models. CoRR abs/2112.10752 (2021). [https://arxiv.org/abs/2112.10752](https://arxiv.org/abs/2112.10752)
255
-
256
- - <span id="ref-podell-2023-sdxl"></span> **Dustin Podell, Zion English, Kyle Lacey et al.** SDXL: Improving Latent Diffusion Models for High-Resolution Image Synthesis. arXiv:2307.01952 (2023). [https://arxiv.org/abs/2307.01952](https://arxiv.org/abs/2307.01952)
257
-
258
- - <span id="ref-jumper-2021-alphafold"></span> **John Jumper, Richard Evans, Alexander Pritzel et al.** Highly accurate protein structure prediction with AlphaFold. Nature 596, 583-589 (2021). [https://doi.org/10.1038/s41586-021-03819-2](https://doi.org/10.1038/s41586-021-03819-2)
259
-
260
- - <span id="ref-devlin-2018-bert"></span> **Jacob Devlin, Ming-Wei Chang, Kenton Lee, Kristina Toutanova.** BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. CoRR abs/1810.04805 (2018). [http://arxiv.org/abs/1810.04805](http://arxiv.org/abs/1810.04805)
261
-
262
- - <span id="ref-atlas-2023-higg"></span> **ATLAS Collaboration.** Measurement of the properties of Higgs boson production at \\(\sqrt{s} = 13\,\text{TeV}\\) in the \\(H \to \gamma\gamma\\) channel using \\(139\,\text{fb}^{-1}\\) of \\(pp\\) collision data with the ATLAS experiment. JHEP 07 (2023) 088. [arXiv:2207.00348](https://arxiv.org/abs/2207.00348), [https://doi.org/10.1007/JHEP07(2023)088](https://doi.org/10.1007/JHEP07(2023)088)
263
-
264
- - <span id="ref-atlas-2023-4top"></span> **ATLAS Collaboration.** Observation of four-top-quark production in the multilepton final state with the ATLAS detector. Eur. Phys. J. C 83 (2023) 496. [arXiv:2303.15061](https://arxiv.org/abs/2303.15061), [https://doi.org/10.1140/epjc/s10052-023-11573-0](https://doi.org/10.1140/epjc/s10052-023-11573-0)
265
-
266
- - <span id="ref-kornblith-2019-cka"></span> **Simon Kornblith, Mohammad Norouzi, Honglak Lee, Geoffrey Hinton.** Similarity of Neural Network Representations Revisited. CoRR abs/1905.00414 (2019). [http://arxiv.org/abs/1905.00414](http://arxiv.org/abs/1905.00414)
267
-
268
- ---
269
-
270
- <!-- Historical/General Physics foundational texts -->
271
-
272
- - <span id="ref-birell-1982-qfields"></span> **N. D. Birell, P. C. W. Davies.** Quantum Fields in Curved Space. Cambridge Univ. Press (1982).
273
-
274
- - <span id="ref-feynman-1954"></span> **R. P. Feynman.** Phys. Rev. 94, 262 (1954).
275
-
276
- - <span id="ref-einstein-1935-epr"></span> **A. Einstein, Yu. Podolsky, N. Rosen.** Phys. Rev. 47, 777 (1935).
277
-
278
- - <span id="ref-berman-1983-stability"></span> **G. P. Berman, Jr., F. M. Izrailev, Jr.** Stability of nonlinear modes. Physica D 88, 445 (1983).
279
-
280
- - <span id="ref-davies-1988-trapped"></span> **E. B. Davies, L. Parns.** Trapped modes in acoustic waveguides. Q. J. Mech. Appl. Math. 51, 477–492 (1988).
281
-
282
- - <span id="ref-witten-2001"></span> **Edward Witten.** hep-th/0106109 (2001). [https://arxiv.org/abs/hep-th/0106109](https://arxiv.org/abs/hep-th/0106109)
283
-
284
- ---
285
-
286
- <!-- Particle physics/data science foundational models -->
287
-
288
- - <span id="ref-beutler-1994-hem"></span> **E. Beutler.** Williams Hematology, 5th Edition, Chapter 7, pp. 654–662. McGraw-Hill, New York (1994).
289
-
290
- - <span id="ref-knuth-1973-fa"></span> **Donald E. Knuth.** The Art of Computer Programming vol. 1: Fundamental Algorithms, 2nd Ed., Addison-Wesley (1973).
291
-
292
- - <span id="ref-smith-2005-philos"></span> **J. S. Smith, G. W. Johnson.** Philos. Trans. R. Soc. London, Ser. B 777, 1395 (2005).
293
-
294
- - <span id="ref-smith-2010-jap-unpub"></span> **W. J. Smith, T. J. Johnson, B. G. Miller.** Surface chemistry and preferential crystal orientation on a silicon surface. J. Appl. Phys. (unpublished, 2010).
295
-
296
- - <span id="ref-smith-2010-jap-sub"></span> **V. K. Smith, K. Johnson, M. O. Klein.** Surface chemistry and preferential crystal orientation on a silicon surface. J. Appl. Phys. (submitted, 2010).
297
-
298
- - <span id="ref-underwood-1988-lowerbounds"></span> **Ulrich Underwood, Ned Net, Paul Pot.** Lower Bounds for Wishful Research Results. Talk at Fanstord University (1988).
299
-
300
- - <span id="ref-johnson-2007-comm"></span> **M. P. Johnson, K. L. Miller, K. Smith.** Personal communication (Jan-May 2007).
301
-
302
- ---
303
-
304
- <!-- Prototypical collider software and tools -->
305
-
306
- - <span id="ref-pytorch-2019"></span> **Adam Paszke et al.** PyTorch: An Imperative Style, High-Performance Deep Learning Library. arXiv:1912.01703 (2019). [http://arxiv.org/abs/1912.01703](http://arxiv.org/abs/1912.01703)
307
-
308
- - <span id="ref-dgl-2019"></span> **Minjie Wang et al.** Deep Graph Library: Towards Efficient and Scalable Deep Learning on Graphs. arXiv:1909.01315 (2019). [http://arxiv.org/abs/1909.01315](http://arxiv.org/abs/1909.01315)
309
-
310
- - <span id="ref-graphnets-2018"></span> **Peter W. Battaglia et al.** Relational inductive biases, deep learning, and graph networks. arXiv:1806.01261 (2018). [http://arxiv.org/abs/1806.01261](http://arxiv.org/abs/1806.01261)
311
-
312
- - <span id="ref-layernorm-2016"></span> **Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton.** Layer Normalization. arXiv:1607.06450 (2016). [https://arxiv.org/abs/1607.06450](https://arxiv.org/abs/1607.06450)
313
-
314
- ---
315
-
316
- <!-- Recent & foundation models in HEP ML -->
317
-
318
- - <span id="ref-wildridge-2024-bumblebee"></span> **Andrew J. Wildridge et al.** Bumblebee: Foundation Model for Particle Physics Discovery. arXiv:2412.07867 (2024). [https://arxiv.org/abs/2412.07867](https://arxiv.org/abs/2412.07867)
319
-
320
- - <span id="ref-katel-2024-jet"></span> **Subash Katel et al.** Learning Symmetry-Independent Jet Representations via Jet-Based Joint Embedding Predictive Architecture. arXiv:2412.05333 (2024). [https://arxiv.org/abs/2412.05333](https://arxiv.org/abs/2412.05333)
321
-
322
- - <span id="ref-araz-2024-pointcloud"></span> **Jack Y. Araz et al.** Point cloud-based diffusion models for the Electron-Ion Collider. arXiv:2410.22421 (2024). [https://arxiv.org/abs/2410.22421](https://arxiv.org/abs/2410.22421)
323
-
324
- - <span id="ref-leigh-2024-maskedparticle"></span> **Matthew Leigh et al.** Is Tokenization Needed for Masked Particle Modelling? arXiv:2409.12589 (2024). [https://arxiv.org/abs/2409.12589](https://arxiv.org/abs/2409.12589)
325
-
326
- - <span id="ref-mikuni-2024-omnilearn"></span> **Vinicius Mikuni, Benjamin Nachman.** OmniLearn: A Method to Simultaneously Facilitate All Jet Physics Tasks. arXiv:2404.16091 (2024). [https://arxiv.org/abs/2404.16091](https://arxiv.org/abs/2404.16091)
327
-
328
- - <span id="ref-zhang-2024-xiwu"></span> **Zhengde Zhang et al.** Xiwu: A Basis Flexible and Learnable LLM for High Energy Physics. arXiv:2404.08001 (2024). [https://arxiv.org/abs/2404.08001](https://arxiv.org/abs/2404.08001)
329
-
330
- - <span id="ref-harris-2024-resimulation"></span> **Philip Harris et al.** Re-Simulation-based Self-Supervised Learning for Pre-Training Foundation Models. arXiv:2403.07066 (2024). [https://arxiv.org/abs/2403.07066](https://arxiv.org/abs/2403.07066)
331
-
332
- - <span id="ref-birk-2024-omnijet"></span> **Joschka Birk, Anna Hallin, Gregor Kasieczka.** OmniJet-$\alpha$: the first cross-task foundation model for particle physics. Machine Learning: Science and Technology. 5(3), 035031 (Aug 2024). [https://doi.org/10.1088/2632-2153/ad66ad](https://doi.org/10.1088/2632-2153/ad66ad)
333
-
334
- - <span id="ref-huang-2024-lmtracking"></span> **Andris Huang et al.** A Language Model for Particle Tracking. arXiv:2402.10239 (2024). [https://arxiv.org/abs/2402.10239](https://arxiv.org/abs/2402.10239)
335
-
336
- - <span id="ref-golling-2024-maskedset"></span> **Tobias Golling et al.** Masked Particle Modeling on Sets: Towards Self-Supervised High Energy Physics Foundation Models. arXiv:2401.13537 (2024). [https://arxiv.org/abs/2401.13537](https://arxiv.org/abs/2401.13537)
337
-
338
- - <span id="ref-liu-2023-gaam"></span> **Junze Liu et al.** Generalizing to new geometries with Geometry-Aware Autoregressive Models (GAAMs) for fast calorimeter simulation. Journal of Instrumentation 18(11), P11003 (Nov 2023). [https://doi.org/10.1088/1748-0221/18/11/p11003](https://doi.org/10.1088/1748-0221/18/11/p11003)
339
-
340
- - <span id="ref-hashemi-2024-gen"></span> **Baran Hashemi et al.** Ultra-high-granularity detector simulation with intra-event aware generative adversarial network and self-supervised relational reasoning. Nature Communications 15(1) (June 2024). [https://doi.org/10.1038/s41467-024-49104-4](https://doi.org/10.1038/s41467-024-49104-4)
341
-
342
- - <span id="ref-vigl-2024-finetune"></span> **Matthias Vigl et al.** Finetuning Foundation Models for Joint Analysis Optimization. arXiv:2401.13536 (2024). [https://arxiv.org/abs/2401.13536](https://arxiv.org/abs/2401.13536)
343
-
344
- - <span id="ref-li-2024-refine"></span> **Chen Li, Hao Cai, Xianyang Jiang.** Refine neutrino events reconstruction with BEiT-3. Journal of Instrumentation 19(6), T06003 (Jun 2024). [https://doi.org/10.1088/1748-0221/19/06/t06003](https://doi.org/10.1088/1748-0221/19/06/t06003)
 
1
  ---
2
  license: mit
3
  ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/config.yaml DELETED
@@ -1,64 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-3
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "config"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- processor_size: 8
35
- hidden_dim_node_encoder: 128
36
- hidden_dim_edge_encoder: 128
37
- hidden_dim_processor: 128
38
- hidden_dim_node_decoder: 128
39
- out_dim: 1
40
-
41
- paths:
42
- data_dir: /global/cfs/projectdirs/atlas/joshua/hackathon_data/stats_100K
43
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/graphs/stats_100K
44
- training_dir: ./training_stats_100K/
45
-
46
- datasets:
47
- - name: ttH_cp_even
48
- load_path: ${paths.data_dir}/ttH_NLO.root
49
- label: 0
50
- - name: ttH_cp_odd
51
- load_path: ${paths.data_dir}/ttH_CPodd.root
52
- label: 1
53
-
54
- root_dataset:
55
- ttree: output
56
- type: torch.bfloat16
57
- particles: ["jet", "ele", "mu", "ph", "MET"]
58
- features: ["pt", "eta", "phi", "energy", "btag", "charge", "node_type"]
59
- globals: []
60
- weights: ""
61
- tracking: []
62
- step_size: 8192
63
- batch_size: 8192
64
- train_val_test_split: [0.75, 0.24, 0.01]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/config_stats_all.yaml DELETED
@@ -1,65 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-4
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "config_stats_all"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- processor_size: 5
35
- hidden_dim_node_encoder: 64
36
- hidden_dim_edge_encoder: 64
37
- hidden_dim_processor: 64
38
- hidden_dim_node_decoder: 64
39
- out_dim: 1
40
-
41
- paths:
42
- data_dir: /global/cfs/projectdirs/atlas/joshua/hackathon_data/stats_all
43
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/graphs/stats_all
44
- training_dir: ./training_stats_all/
45
-
46
- datasets:
47
- - name: ttH_cp_even
48
- load_path: ${paths.data_dir}/ttH_NLO.root
49
- label: 0
50
- - name: ttH_cp_odd
51
- load_path: ${paths.data_dir}/ttH_CPodd.root
52
- label: 1
53
-
54
- root_dataset:
55
- ttree: output
56
- type: torch.bfloat16
57
- particles: ["jet", "ele", "mu", "ph", "MET"]
58
- features: ["pt", "eta", "phi", "energy", "btag", "charge", "node_type"]
59
- globals: []
60
- weights: ""
61
- tracking: []
62
- step_size: 81920
63
- batch_size: 8192
64
- train_val_test_split: [0.75, 0.24, 0.01]
65
- prebatch: True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/tHjb_CP_0_vs_45.yaml DELETED
@@ -1,79 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-3
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "config"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- processor_size: 8
35
- hidden_dim_node_encoder: 128
36
- hidden_dim_edge_encoder: 128
37
- hidden_dim_processor: 128
38
- hidden_dim_node_decoder: 128
39
- global_emb_dim: 128
40
- out_dim: 1
41
-
42
- paths:
43
- data_dir: /global/cfs/projectdirs/atlas/joshua/ttHCP/ntuples/v02/preselection/merged_fixed/train/
44
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/ttHCP/graphs/tHjb_CP_0_vs_45/
45
- training_dir: ./training_tHjb_CP_0_vs_45/
46
-
47
- datasets:
48
- - name: tHjb_cp_0_had
49
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_had_scaled.root
50
- label: 0
51
- - name: tHjb_cp_0_lep
52
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_lep_scaled.root
53
- label: 0
54
- - name: tHjb_cp_45_had
55
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_45_AF3_had_scaled.root
56
- label: 1
57
- - name: tHjb_cp_45_lep
58
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_45_AF3_lep_scaled.root
59
- label: 1
60
-
61
- root_dataset:
62
- ttree: output
63
- dtype: torch.bfloat16
64
- features:
65
- # pt, eta, phi, energy, btag, charge, node_type
66
- jet: [m_jet_pt, m_jet_eta, m_jet_phi, CALC_E, m_jet_PCbtag, 0, 0]
67
- electron: [m_el_pt, m_el_eta, m_el_phi, CALC_E, 0, m_el_charge, 1]
68
- muon: [m_mu_pt, m_mu_eta, m_mu_phi, CALC_E, 0, m_mu_charge, 2]
69
- photon: [ph_pt_myy, ph_eta, ph_phi, CALC_E, 0, 0, 3]
70
- met: [m_met, 0, m_met_phi, CALC_E, 0, 0, 4]
71
- globals: [NUM_NODES]
72
- weights: m_weightXlumi
73
- tracking: []
74
- step_size: 16384
75
- batch_size: 16384
76
- train_val_test_split: [0.5, 0.25, 0.25]
77
- prebatch:
78
- enabled: True
79
- chunk_size: 512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/tHjb_CP_0_vs_90.yaml DELETED
@@ -1,87 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-3
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "tHjb_CP_0_vs_90"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- module: models.MeshGraphNet
35
- class: MeshGraphNet
36
- args:
37
- base_gnn:
38
- input_dim_nodes: 7
39
- input_dim_edges: 3
40
- output_dim: 128
41
- processor_size: 8
42
- hidden_dim_node_encoder: 128
43
- hidden_dim_edge_encoder: 128
44
- hidden_dim_processor: 128
45
- hidden_dim_node_decoder: 128
46
- global_emb_dim: 128
47
- global_feat_dim: 1
48
- out_dim: 1
49
-
50
- paths:
51
- data_dir: /global/cfs/projectdirs/atlas/joshua/ttHCP/ntuples/v02/preselection/merged_fixed/train/
52
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/ttHCP/graphs/tHjb_CP_0_vs_90/
53
- training_dir: ./tHjb_CP_0_vs_90/
54
-
55
- datasets:
56
- - name: tHjb_cp_0_had
57
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_had_scaled.root
58
- label: 0
59
- - name: tHjb_cp_0_lep
60
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_lep_scaled.root
61
- label: 0
62
- - name: tHjb_cp_90_had
63
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_had_scaled.root
64
- label: 1
65
- - name: tHjb_cp_90_lep
66
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_lep_scaled.root
67
- label: 1
68
-
69
- root_dataset:
70
- ttree: output
71
- dtype: torch.bfloat16
72
- features:
73
- # pt, eta, phi, energy, btag, charge, node_type
74
- jet: [m_jet_pt, m_jet_eta, m_jet_phi, CALC_E, m_jet_PCbtag, 0, 0]
75
- electron: [m_el_pt, m_el_eta, m_el_phi, CALC_E, 0, m_el_charge, 1]
76
- muon: [m_mu_pt, m_mu_eta, m_mu_phi, CALC_E, 0, m_mu_charge, 2]
77
- photon: [ph_pt_myy, ph_eta, ph_phi, CALC_E, 0, 0, 3]
78
- met: [m_met, 0, m_met_phi, CALC_E, 0, 0, 4]
79
- globals: [NUM_NODES]
80
- weights: 1
81
- tracking: []
82
- step_size: 16384
83
- batch_size: 16384
84
- train_val_test_split: [0.5, 0.25, 0.25]
85
- prebatch:
86
- enabled: True
87
- chunk_size: 512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/tHjb_CP_0_vs_90_edge_network.yaml DELETED
@@ -1,82 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-3
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "tHjb_CP_0_vs_90_edge_network"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- module: models.Edge_Network
35
- class: Edge_Network
36
- args:
37
- input_dim_nodes: 7
38
- input_dim_edges: 3
39
- input_dim_globals: 1
40
- hid_size: 64
41
- n_layers: 4
42
- n_proc_steps: 4
43
- out_dim: 1
44
-
45
- paths:
46
- data_dir: /global/cfs/projectdirs/atlas/joshua/ttHCP/ntuples/v02/preselection/merged_fixed/train/
47
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/ttHCP/graphs/tHjb_CP_0_vs_90/
48
- training_dir: ./tHjb_CP_0_vs_90_edge_network/
49
-
50
- datasets:
51
- - name: tHjb_cp_0_had
52
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_had_scaled.root
53
- label: 0
54
- - name: tHjb_cp_0_lep
55
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_lep_scaled.root
56
- label: 0
57
- - name: tHjb_cp_90_had
58
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_had_scaled.root
59
- label: 1
60
- - name: tHjb_cp_90_lep
61
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_lep_scaled.root
62
- label: 1
63
-
64
- root_dataset:
65
- ttree: output
66
- dtype: torch.bfloat16
67
- features:
68
- # pt, eta, phi, energy, btag, charge, node_type
69
- jet: [m_jet_pt, m_jet_eta, m_jet_phi, CALC_E, m_jet_PCbtag, 0, 0]
70
- electron: [m_el_pt, m_el_eta, m_el_phi, CALC_E, 0, m_el_charge, 1]
71
- muon: [m_mu_pt, m_mu_eta, m_mu_phi, CALC_E, 0, m_mu_charge, 2]
72
- photon: [ph_pt_myy, ph_eta, ph_phi, CALC_E, 0, 0, 3]
73
- met: [m_met, 0, m_met_phi, CALC_E, 0, 0, 4]
74
- globals: [NUM_NODES]
75
- weights: 1
76
- tracking: []
77
- step_size: 16384
78
- batch_size: 16384
79
- train_val_test_split: [0.5, 0.25, 0.25]
80
- prebatch:
81
- enabled: True
82
- chunk_size: 512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/configs/tHjb_CP_0_vs_90_globals.yaml DELETED
@@ -1,84 +0,0 @@
1
- # ignore_header_test
2
- # Copyright 2023 Stanford University
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
-
16
- random_seed: 2
17
-
18
- scheduler:
19
- lr: 1.E-3
20
- lr_decay: 1.E-3
21
-
22
- training:
23
- epochs: 100
24
-
25
- checkpoints:
26
- ckpt_path: "checkpoints"
27
- ckpt_name: "tHjb_CP_0_vs_90_globals"
28
-
29
- performance:
30
- amp: False
31
- jit: False
32
-
33
- architecture:
34
- base_gnn:
35
- input_dim_nodes: 7
36
- input_dim_edges: 3
37
- output_dim: 128
38
- processor_size: 8
39
- hidden_dim_node_encoder: 128
40
- hidden_dim_edge_encoder: 128
41
- hidden_dim_processor: 128
42
- hidden_dim_node_decoder: 128
43
- global_emb_dim: 128
44
- global_feat_dim: 5
45
- out_dim: 1
46
-
47
- paths:
48
- data_dir: /global/cfs/projectdirs/atlas/joshua/ttHCP/ntuples/v02/preselection/merged_fixed/train/
49
- save_dir: /pscratch/sd/j/joshuaho/physicsnemo/ttHCP/graphs/tHjb_CP_0_vs_90_globals/
50
- training_dir: ./tHjb_CP_0_vs_90_globals/
51
-
52
- datasets:
53
- - name: tHjb_cp_0_had
54
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_had_scaled.root
55
- label: 0
56
- - name: tHjb_cp_0_lep
57
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_0_AF3_lep_scaled.root
58
- label: 0
59
- - name: tHjb_cp_90_had
60
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_had_scaled.root
61
- label: 1
62
- - name: tHjb_cp_90_lep
63
- load_path: ${paths.data_dir}/merged_aMCPy8_tHjb125_CP_90_AF3_lep_scaled.root
64
- label: 1
65
-
66
- root_dataset:
67
- ttree: output
68
- dtype: torch.bfloat16
69
- features:
70
- # pt, eta, phi, energy, btag, charge, node_type
71
- jet: [m_jet_pt, m_jet_eta, m_jet_phi, CALC_E, m_jet_PCbtag, 0, 0]
72
- electron: [m_el_pt, m_el_eta, m_el_phi, CALC_E, 0, m_el_charge, 1]
73
- muon: [m_mu_pt, m_mu_eta, m_mu_phi, CALC_E, 0, m_mu_charge, 2]
74
- photon: [ph_pt_myy, ph_eta, ph_phi, CALC_E, 0, 0, 3]
75
- met: [m_met, 0, m_met_phi, CALC_E, 0, 0, 4]
76
- globals: [NUM_NODES, eta_H, pt_H, eta_recotop1, pT_recotop1]
77
- weights: 1
78
- tracking: []
79
- step_size: 16384
80
- batch_size: 16384
81
- train_val_test_split: [0.5, 0.25, 0.25]
82
- prebatch:
83
- enabled: True
84
- chunk_size: 512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/dataset/Dataset.py DELETED
@@ -1,243 +0,0 @@
1
- import os
2
- import uproot
3
- import dgl
4
- import torch
5
- import numpy as np
6
- from omegaconf import DictConfig
7
- from typing import List
8
- from concurrent.futures import ProcessPoolExecutor, as_completed
9
- from tqdm import tqdm
10
-
11
- from dataset import GraphBuilder
12
- from dataset import Graphs
13
- from dataset import Normalization
14
-
15
- from dgl.dataloading import GraphDataLoader
16
-
17
- class Dataset:
18
- def __init__(
19
- self,
20
- name: str,
21
- label: int,
22
- load_path: str,
23
- save_path: str,
24
- dtype: torch.dtype,
25
- device: str,
26
- cfg: DictConfig
27
- ):
28
- self.name = name
29
- self.label = label
30
- self.load_path = load_path
31
- self.save_path = save_path
32
- self.dtype = dtype
33
- self.data = None
34
- self.device = device
35
-
36
- self.ttree = cfg.ttree
37
- self.features = cfg.features
38
- self.weights = cfg.weights
39
- self.globals = cfg.globals
40
- self.tracking = cfg.tracking
41
- self.step_size = cfg.step_size
42
- self.batch_size = cfg.batch_size
43
-
44
- self.prebatch = cfg.get('prebatch', {'enabled': False})
45
-
46
- self.train_val_test_split = cfg.train_val_test_split
47
- assert np.sum(self.train_val_test_split) == 1, "train_val_test_split must sum to 1"
48
-
49
- print(f"initializing dataset {name} with dtype {self.dtype}")
50
-
51
- def get_branches(self) -> List[str]:
52
- node_branches = [
53
- branches
54
- for particle in self.features.values()
55
- for branches in particle
56
- if isinstance(branches, str) and (branches != "CALC_E" or branches != "NUM_NODES")
57
- ]
58
- global_branches = [x for x in self.globals if isinstance(x, str)]
59
- weight_branch = [self.weights] if isinstance(self.weights, str) else []
60
- tracking_branches = [x for x in self.tracking if isinstance(x, str)]
61
- label_branch = [self.label] if isinstance(self.label, str) else []
62
-
63
- return node_branches + global_branches + weight_branch + tracking_branches + label_branch
64
-
65
- def process(self):
66
- branches = self.get_branches()
67
- with uproot.open(f"{self.load_path}:{self.ttree}") as tree:
68
- available_branches = set(tree.keys())
69
- num_entries = tree.num_entries
70
-
71
- print(f"getting branches: {branches}")
72
-
73
- num_cpus = os.cpu_count()
74
- total_chunks = np.ceil(num_entries / self.step_size)
75
-
76
- with ProcessPoolExecutor(max_workers=num_cpus) as executor:
77
- futures = []
78
-
79
- with tqdm(
80
- uproot.iterate(
81
- f"{self.load_path}:{self.ttree}",
82
- expressions=[b for b in branches if b in available_branches],
83
- step_size=self.step_size,
84
- library="ak"
85
- ),
86
- desc="loading root file",
87
- total=total_chunks,
88
- position=0,
89
- leave=True
90
- ) as pbar:
91
-
92
- for chunk_id, arrays in enumerate(pbar):
93
-
94
- cfg = GraphBuilder.ChunkConfig(
95
- name=self.name,
96
- label=self.label,
97
- chunk_id=chunk_id,
98
- batch_size=self.batch_size,
99
- arrays=arrays,
100
- features=self.features,
101
- globals=self.globals,
102
- tracking=self.tracking,
103
- weights=self.weights,
104
- branches=branches,
105
- dtype=self.dtype,
106
- save_path=self.save_path,
107
- prebatch = self.prebatch,
108
- )
109
-
110
- futures.append(executor.submit(GraphBuilder.process_chunk, cfg))
111
-
112
- for idx, future in enumerate(as_completed(futures)):
113
- try:
114
- future.result()
115
- except Exception as e:
116
- import traceback
117
- print(f"exception in chunk: {idx}")
118
- traceback.print_exception(type(e), e, e.__traceback__)
119
- return
120
-
121
- def load(self):
122
- with uproot.open(f"{self.load_path}:{self.ttree}") as tree:
123
- num_entries = tree.num_entries
124
- total_chunks = int(np.ceil(num_entries / self.step_size))
125
-
126
- chunk_files = [f"{self.save_path}/{self.name}_{chunk_id:04d}.bin" for chunk_id in range(total_chunks)]
127
- if not all(os.path.exists(f) for f in chunk_files):
128
- print("graphs not found. processing root file...")
129
- self.process()
130
-
131
- graph_tuple_list = []
132
-
133
- for chunk_id, f in enumerate(chunk_files):
134
- if chunk_id < total_chunks - 1:
135
- if (self.prebatch.enabled):
136
- n_graphs = self.step_size // self.prebatch.chunk_size
137
- else:
138
- n_graphs = self.step_size
139
- else:
140
- if (self.prebatch.enabled):
141
- n_graphs = (num_entries - self.step_size * (total_chunks - 1)) // self.prebatch.chunk_size + 1
142
- else:
143
- n_graphs = num_entries - self.step_size * (total_chunks - 1)
144
- graph_tuple_list.extend((f, idx) for idx in range(n_graphs))
145
-
146
- split = self.train_val_test_split
147
- n_total = len(graph_tuple_list)
148
- n_train = int(split[0] * n_total)
149
- n_val = int(split[1] * n_total)
150
-
151
- train_tuples = graph_tuple_list[:n_train]
152
- val_tuples = graph_tuple_list[n_train:n_train + n_val]
153
- test_tuples = graph_tuple_list[n_train + n_val:]
154
- return train_tuples, val_tuples, test_tuples
155
-
156
- class GraphTupleDataset:
157
- def __init__(self, tuple_list, stats):
158
- self.tuple_list = tuple_list
159
- self.stats = stats
160
- self.cache = {}
161
-
162
- def __len__(self):
163
- return len(self.tuple_list)
164
-
165
- def __getitem__(self, idx):
166
- f, graph_idx = self.tuple_list[idx]
167
- if f in self.cache:
168
- g = self.cache[f]
169
- else:
170
- g = Graphs.load_graphs(f)
171
- g.normalize(self.stats)
172
- self.cache[f] = g
173
- return g[graph_idx]
174
-
175
- @staticmethod
176
- def collate_fn(samples):
177
- all_graphs = []
178
- all_metadata = {}
179
-
180
- # Initialize keys in all_metadata from the first sample
181
- for k in samples[0][1]:
182
- all_metadata[k] = []
183
-
184
- for graph, metadata in samples:
185
- all_graphs.append(graph)
186
- for k, v in metadata.items():
187
- all_metadata[k].append(v)
188
-
189
- # Stack or concatenate metadata for each key
190
- for k in all_metadata:
191
- # If v is a tensor, stack or cat as appropriate
192
- # Use torch.cat if v is already [N, ...] (e.g. labels, features)
193
- # Use torch.stack if v is scalar or needs new dimension
194
- try:
195
- all_metadata[k] = torch.cat(all_metadata[k], dim=0)
196
- except Exception:
197
- all_metadata[k] = torch.stack(all_metadata[k], dim=0)
198
-
199
- batched_graph = dgl.batch(all_graphs)
200
- return batched_graph, all_metadata
201
-
202
- def get_dataset(cfg: DictConfig, device):
203
-
204
- all_train = []
205
- all_val = []
206
- all_test = []
207
-
208
- dtype_str = getattr(cfg.root_dataset, "dtype", "torch.float32")
209
- if isinstance(dtype_str, str) and dtype_str.startswith("torch."):
210
- dtype = getattr(torch, dtype_str.split(".")[-1], torch.float32)
211
- else:
212
- dtype = torch.float32
213
-
214
- for ds in cfg.datasets:
215
- name = ds['name']
216
- load_path = ds.get('load_path', f"{cfg.paths.data_dir}/{name}.root")
217
- save_path = ds.get('save_path', f"{cfg.paths.save_dir}/")
218
- datastet = Dataset(name, ds.get('label'), load_path, save_path, dtype, device, cfg.root_dataset)
219
- train, val, test = datastet.load()
220
- all_train.extend(train)
221
- all_val.extend(val)
222
- all_test.extend(test)
223
-
224
- stats = Normalization.global_stats(f"{cfg.paths.save_dir}/stats/", dtype=dtype)
225
-
226
- train_dataset = GraphTupleDataset(all_train, stats)
227
- val_dataset = GraphTupleDataset(all_val, stats)
228
- test_dataset = GraphTupleDataset(all_test, stats)
229
-
230
- if (cfg.root_dataset.get('prebatch', False)):
231
- batch_size = cfg.root_dataset.batch_size // cfg.root_dataset.prebatch.chunk_size
232
- collate_fn = GraphTupleDataset.collate_fn
233
- else:
234
- batch_size = cfg.root_dataset.batch_size
235
- collate_fn = None
236
-
237
- train_loader = GraphDataLoader(train_dataset, batch_size=batch_size, shuffle=True, pin_memory=True, num_workers=5, drop_last=False, collate_fn=collate_fn)
238
- val_loader = GraphDataLoader(val_dataset, batch_size=batch_size, shuffle=False, pin_memory=True, num_workers=5, drop_last=False, collate_fn=collate_fn)
239
- test_loader = GraphDataLoader(test_dataset, batch_size=batch_size, shuffle=False, pin_memory=True, num_workers=0, drop_last=False, collate_fn=collate_fn)
240
-
241
- print("all data loaded successfully")
242
- print(f"train: {len(train_dataset)}, val: {len(val_dataset)}, test: {len(test_dataset)}")
243
- return train_loader, val_loader, test_loader
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/dataset/GraphBuilder.py DELETED
@@ -1,162 +0,0 @@
1
- import dgl
2
- import torch
3
- import numpy as np
4
- import awkward as ak
5
- from dataclasses import dataclass
6
- from typing import List, Any, Union
7
-
8
- from dataset.Graphs import Graphs, save_graphs
9
- from dataset import Normalization
10
-
11
- @dataclass
12
- class ChunkConfig:
13
- name: str
14
- label: Union[str, int]
15
- chunk_id: int
16
- batch_size: int
17
- arrays: List[Any]
18
- features: List[Any]
19
- globals: List[Any]
20
- weights: Union[str, float]
21
- tracking: List[Any]
22
- branches: List[Any]
23
- dtype: torch.dtype
24
- save_path: str
25
- prebatch: dict
26
-
27
- def process_chunk(cfg: ChunkConfig):
28
- # Collect everything as lists first
29
- graph_list = []
30
- meta_dict = {
31
- 'globals': [],
32
- 'label': [],
33
- 'weight': [],
34
- 'tracking': [],
35
- 'batch_num_nodes': [],
36
- 'batch_num_edges': [],
37
- }
38
-
39
- for i in range(len(cfg.arrays)):
40
- g, meta = process_single_entry(cfg, i)
41
- graph_list.append(g)
42
- for k in meta_dict:
43
- meta_dict[k].append(meta[k])
44
-
45
- # Stack all metadata fields into tensors
46
- for k in meta_dict:
47
- meta_dict[k] = torch.stack(meta_dict[k])
48
-
49
- graphs = Graphs(graphs=graph_list, metadata=meta_dict)
50
- Normalization.save_stats(graphs, f"{cfg.save_path}/stats/{cfg.name}_{cfg.chunk_id:04d}.json")
51
-
52
- if getattr(cfg.prebatch, "enabled", False):
53
- graphs.shuffle()
54
- graphs.batch(cfg.prebatch["chunk_size"])
55
-
56
- save_graphs(graphs, f"{cfg.save_path}/{cfg.name}_{cfg.chunk_id:04d}.bin")
57
-
58
- def process_single_entry(cfg, i):
59
- # 1) node features
60
- node_features: List[torch.Tensor] = []
61
-
62
- for particle, branch_list in cfg.features.items():
63
- feature_tensors: List[torch.Tensor] = []
64
- for branch in branch_list:
65
- if branch == "CALC_E":
66
- pT = feature_tensors[0]
67
- eta = feature_tensors[1]
68
- val = pT * torch.cosh(eta)
69
- elif isinstance(branch, str):
70
- arr = cfg.arrays[branch][i]
71
- val = torch.from_numpy(ak.to_numpy(arr)).to(cfg.dtype)
72
- else:
73
- length = feature_tensors[0].shape[0]
74
- val = torch.full((length,), float(branch), dtype=cfg.dtype)
75
- feature_tensors.append(val)
76
-
77
- if feature_tensors and feature_tensors[0].numel() > 0:
78
- block = torch.stack(feature_tensors, dim=1)
79
- node_features.append(block)
80
-
81
- node_features = torch.cat(node_features, dim=0) if node_features else torch.empty((0, len(cfg.features)), dtype=cfg.dtype)
82
-
83
- # 2) global features
84
- global_feat_list: List[torch.Tensor] = []
85
- for b in cfg.globals:
86
- if b == "NUM_NODES":
87
- global_feat_list.append(torch.tensor([len(node_features)], dtype=cfg.dtype))
88
- else:
89
- arr = cfg.arrays[b][i]
90
- global_feat_list.append(torch.from_numpy(ak.to_numpy(arr)).to(cfg.dtype))
91
- global_feat = torch.cat(global_feat_list, dim=0) if global_feat_list else torch.zeros((1,), dtype=cfg.dtype)
92
-
93
- # 3) tracking
94
- tracking_list: List[torch.Tensor] = []
95
- for b in cfg.tracking:
96
- arr = cfg.arrays[b][i]
97
- tracking_list.append(torch.from_numpy(ak.to_numpy(arr)).to(cfg.dtype))
98
- tracking = torch.cat(tracking_list, dim=0) if tracking_list else torch.zeros((1,), dtype=cfg.dtype)
99
-
100
- # 4) weight
101
- weight = float(cfg.arrays[cfg.weights][i]) if isinstance(cfg.weights, str) else cfg.weights
102
- weight = torch.tensor(weight, dtype=cfg.dtype)
103
-
104
- # 5) label
105
- label = float(cfg.arrays[cfg.label][i]) if isinstance(cfg.label, str) else cfg.label
106
- label = torch.tensor(label, dtype=cfg.dtype)
107
-
108
- # 6) make the DGLGraph
109
- g = make_graph(node_features, dtype=cfg.dtype)
110
-
111
- # 7) batch_num_nodes and batch_num_edges
112
- batch_num_nodes = g.batch_num_nodes()
113
- batch_num_edges = g.batch_num_edges()
114
-
115
- meta = {
116
- 'globals': global_feat,
117
- 'label': label,
118
- 'weight': weight,
119
- 'tracking': tracking,
120
- 'batch_num_nodes': batch_num_nodes,
121
- 'batch_num_edges': batch_num_edges,
122
- }
123
- return g, meta
124
-
125
- src_dst_cache = {}
126
- def get_src_dst(num_nodes):
127
- if num_nodes not in src_dst_cache:
128
- src, dst = torch.meshgrid(torch.arange(num_nodes), torch.arange(num_nodes), indexing='ij')
129
- src_dst_cache[num_nodes] = (src.flatten(), dst.flatten())
130
- return src_dst_cache[num_nodes]
131
-
132
- @torch.jit.script
133
- def compute_edge_features(eta, phi, src, dst):
134
- deta = eta[src] - eta[dst]
135
- dphi = phi[src] - phi[dst]
136
- dphi = torch.remainder(dphi + np.pi, 2 * np.pi) - np.pi
137
- dR = torch.sqrt(deta ** 2 + dphi ** 2)
138
- edge_features = torch.stack([dR, deta, dphi], dim=1)
139
- return edge_features
140
-
141
- def make_graph(node_features: torch.tensor, dtype=torch.float32):
142
-
143
- num_nodes = node_features.shape[0]
144
- if num_nodes == 0:
145
- g = dgl.graph(([], []))
146
- g.ndata['features'] = node_features
147
- g.edata['features'] = torch.empty((0, 3), dtype=dtype)
148
- g.globals = torch.tensor([0], dtype=dtype)
149
- return g
150
-
151
- src, dst = get_src_dst(num_nodes)
152
- src = src.flatten()
153
- dst = dst.flatten()
154
- g = dgl.graph((src, dst))
155
- g.ndata['features'] = node_features
156
-
157
- eta = node_features[:, 1]
158
- phi = node_features[:, 2]
159
- edge_features = compute_edge_features(eta, phi, src, dst)
160
- g.edata['features'] = edge_features
161
-
162
- return g
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/dataset/Graphs.py DELETED
@@ -1,88 +0,0 @@
1
- import dgl
2
- import torch
3
- from dataclasses import dataclass, field
4
- from typing import List, Dict
5
-
6
- @dataclass
7
- class Graphs:
8
- graphs: List[dgl.DGLGraph]
9
- metadata: Dict[str, torch.Tensor]
10
-
11
- def __len__(self):
12
- return len(self.graphs)
13
-
14
- def __getitem__(self, idx):
15
- meta = {k: v[idx] for k, v in self.metadata.items()}
16
- return self.graphs[idx], meta
17
-
18
- def shuffle(self):
19
- idx = torch.randperm(len(self.graphs))
20
- self.graphs = [self.graphs[i] for i in idx]
21
- for k in self.metadata:
22
- self.metadata[k] = self.metadata[k][idx]
23
-
24
- def batch(self, batch_size, node_feature_dim=None, dtype=None):
25
- """
26
- In-place batching: after this, self.graphs is a list of batched DGLGraphs,
27
- and self.metadata[k] is a tensor of shape [num_batches, batch_size, ...].
28
- """
29
- batched_graphs = []
30
- batched_meta = {k: [] for k in self.metadata}
31
- N = len(self.graphs)
32
-
33
- # Infer node_feature_dim and dtype if not specified
34
- if node_feature_dim is None and N > 0:
35
- feats = self.graphs[0].ndata['features']
36
- node_feature_dim = feats.shape[1] if feats.ndim > 1 else 1
37
- if dtype is None and N > 0:
38
- dtype = self.graphs[0].ndata['features'].dtype
39
-
40
- for start in range(0, N, batch_size):
41
- end = start + batch_size
42
- batch_graphs = self.graphs[start:end]
43
- batch_meta = {k: v[start:end] for k, v in self.metadata.items()}
44
-
45
- # Padding if needed
46
- pad_count = batch_size - len(batch_graphs)
47
- if pad_count > 0:
48
- dummy_graph = dgl.graph(([], []))
49
- dummy_graph.ndata['features'] = torch.empty((0, node_feature_dim), dtype=dtype)
50
- dummy_graph.edata['features'] = torch.empty((0, 3), dtype=dtype) # assuming 3 edge features
51
- batch_graphs += [dummy_graph] * pad_count
52
-
53
- # Pad metadata with zeros
54
- for k, v in batch_meta.items():
55
- shape = list(v[0].shape) if len(v) > 0 else []
56
- pad_tensor = torch.zeros([pad_count] + shape, dtype=v.dtype, device=v.device)
57
- batch_meta[k] = torch.cat([v, pad_tensor], dim=0)
58
- else:
59
- for k, v in batch_meta.items():
60
- batch_meta[k] = torch.stack(v, dim=0) if isinstance(v, list) else v
61
-
62
- batched_graphs.append(dgl.batch(batch_graphs))
63
- for k in batched_meta:
64
- batched_meta[k].append(batch_meta[k])
65
-
66
- # Now stack along a new axis: [num_batches, batch_size, ...]
67
- for k in batched_meta:
68
- self.metadata[k] = torch.stack(batched_meta[k], dim=0)
69
-
70
- self.graphs = batched_graphs
71
-
72
- def normalize(self, stats):
73
- node_mean, node_std, _ = stats['node']
74
- edge_mean, edge_std, _ = stats['edge']
75
- for g in self.graphs:
76
- g.ndata['features'] = (g.ndata['features'] - node_mean) / node_std
77
- g.edata['features'] = (g.edata['features'] - edge_mean) / edge_std
78
-
79
- def save_graphs(graphs: Graphs, f: str):
80
- meta_to_save = {k: v for k, v in graphs.metadata.items()}
81
- dgl.save_graphs(f, graphs.graphs, meta_to_save)
82
-
83
- def load_graphs(f: str) -> Graphs:
84
- g, meta = dgl.load_graphs(f)
85
- for k in meta:
86
- if not isinstance(meta[k], torch.Tensor):
87
- meta[k] = torch.stack(meta[k])
88
- return Graphs(graphs=g, metadata=meta)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/dataset/Normalization.py DELETED
@@ -1,144 +0,0 @@
1
- import torch
2
- import json
3
- import os
4
- from dataset.Graphs import Graphs
5
- from typing import List, Dict, Tuple
6
-
7
- def combine_feature_stats(chunks: List[Dict]) -> Tuple[torch.Tensor, torch.Tensor, int]:
8
- """
9
- Combine mean/std/count from multiple chunks using Welford's algorithm.
10
- Returns combined mean, std, and total count.
11
- """
12
- n_total = 0
13
- mean_total = None
14
- M2_total = None
15
-
16
- for chunk in chunks:
17
- n_k = chunk['count']
18
- if n_k == 0:
19
- continue
20
-
21
- mean_k = torch.tensor(chunk['mean'])
22
- std_k = torch.tensor(chunk['std'])
23
- M2_k = (std_k ** 2) * n_k
24
-
25
- if n_total == 0:
26
- mean_total = mean_k
27
- M2_total = M2_k
28
- n_total = n_k
29
- else:
30
- delta = mean_k - mean_total
31
- N = n_total + n_k
32
- mean_total += delta * (n_k / N)
33
- M2_total += M2_k + (delta ** 2) * (n_total * n_k / N)
34
- n_total = N
35
-
36
- if n_total == 0:
37
- return torch.tensor([]), torch.tensor([]), 0
38
-
39
- std_total = torch.sqrt(M2_total / n_total)
40
- return mean_total, std_total, n_total
41
-
42
- def global_stats(dirpath: str, dtype: torch.dtype) -> Dict[str, Tuple[torch.Tensor, torch.Tensor, int]]:
43
- """
44
- Load all JSON stats files in a directory, combine node, edge, and global stats,
45
- and optionally save the combined stats as JSON to `save_path`.
46
- """
47
-
48
- combined_stats_path = os.path.join(dirpath, "global_stats.json")
49
-
50
- if not os.path.exists(combined_stats_path):
51
- stats_list = []
52
- for fname in os.listdir(dirpath):
53
- if fname.endswith('.json'):
54
- with open(os.path.join(dirpath, fname), 'r') as f:
55
- stats_list.append(json.load(f))
56
-
57
- node_stats = [s['node'] for s in stats_list]
58
- edge_stats = [s['edge'] for s in stats_list]
59
-
60
- combined = {
61
- 'node': combine_feature_stats(node_stats),
62
- 'edge': combine_feature_stats(edge_stats),
63
- }
64
-
65
- combined_json = {}
66
- for key, (mean, std, count) in combined.items():
67
- combined_json[key] = {
68
- 'mean': mean.tolist() if mean.numel() > 0 else [],
69
- 'std': std.tolist() if std.numel() > 0 else [],
70
- 'count': count,
71
- }
72
-
73
- with open(combined_stats_path, 'w') as f:
74
- json.dump(combined_json, f, indent=4)
75
-
76
- with open(combined_stats_path, 'r') as f:
77
- combined_json = json.load(f)
78
-
79
- def to_tensor(d):
80
- mean = torch.tensor(d['mean'], dtype=dtype) if d['mean'] else torch.tensor([], dtype=dtype)
81
- std = torch.tensor(d['std'], dtype=dtype) if d['std'] else torch.tensor([], dtype=dtype)
82
- count = d['count']
83
- return mean, std, count
84
-
85
- return {
86
- 'node': to_tensor(combined_json['node']),
87
- 'edge': to_tensor(combined_json['edge']),
88
- }
89
-
90
- def compute_stats(feats, eps=1e-6):
91
- mean = feats.mean(dim=0)
92
- if feats.size(0) > 1:
93
- var = ((feats - mean) ** 2).mean(dim=0)
94
- else:
95
- var = torch.zeros_like(mean)
96
- std = torch.sqrt(var)
97
- std = torch.where(std < eps, torch.full_like(std, eps), std)
98
-
99
- return mean, std
100
-
101
- def save_stats(graphs: 'Graphs', filepath: str, categorical_unique_threshold=50):
102
- """
103
- Compute and save normalization stats (mean, std, counts) for node and edge features.
104
- Categorical features (few unique values) have normalization disabled (mean=0, std=1).
105
- """
106
- if len(graphs) == 0:
107
- raise ValueError("No graphs to compute stats from.")
108
-
109
- # Node and edge features
110
- all_node_feats = torch.cat([g.ndata['features'] for g, _ in graphs], dim=0)
111
- all_edge_feats = torch.cat([g.edata['features'] for g, _ in graphs], dim=0)
112
-
113
- counts = {
114
- 'node': all_node_feats.size(0),
115
- 'edge': all_edge_feats.size(0),
116
- }
117
-
118
- node_mean, node_std = compute_stats(all_node_feats)
119
- edge_mean, edge_std = compute_stats(all_edge_feats)
120
-
121
- categorical_mask = torch.tensor([
122
- torch.unique(all_node_feats[:, i]).numel() < categorical_unique_threshold
123
- for i in range(node_mean.size(0))
124
- ], dtype=torch.bool)
125
- node_mean[categorical_mask] = 0.0
126
- node_std[categorical_mask] = 1.0
127
-
128
- stats = {
129
- 'node': {
130
- 'mean': node_mean.tolist(),
131
- 'std': node_std.tolist(),
132
- 'count': counts['node'],
133
- },
134
- 'edge': {
135
- 'mean': edge_mean.tolist(),
136
- 'std': edge_std.tolist(),
137
- 'count': counts['edge'],
138
- },
139
- }
140
-
141
- os.makedirs(os.path.dirname(filepath), exist_ok=True)
142
-
143
- with open(filepath, 'w') as f:
144
- json.dump(stats, f, indent=4)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/metrics.py DELETED
@@ -1,110 +0,0 @@
1
- import torch
2
- import numpy as np
3
- import torch.nn.functional as F
4
-
5
- def bce(input, target, weights=None):
6
-
7
- if input.shape != target.shape:
8
- if input.shape[-1] == 1 and input.shape[:-1] == target.shape:
9
- input = input.squeeze(-1)
10
- elif target.shape[-1] == 1 and target.shape[:-1] == input.shape:
11
- target = target.squeeze(-1)
12
-
13
- loss = F.binary_cross_entropy_with_logits(input, target, reduction='none')
14
- return torch.mean(loss)
15
-
16
- def weighted_bce(input, target, weights=None):
17
- """
18
- Compute a weighted and label-normalized binary cross entropy (BCE) loss.
19
-
20
- For each unique label in the target tensor, the BCE loss is computed and weighted,
21
- then normalized by the sum of weights for that label. The final loss is the mean
22
- of these per-label normalized losses.
23
-
24
- Args:
25
- input (Tensor): Predicted logits of shape (N, ...).
26
- target (Tensor): Ground truth labels of shape (N, ...), with discrete label values.
27
- weights (Tensor or None): Optional tensor of per-sample weights, same shape as input/target.
28
-
29
- Returns:
30
- Tensor: Scalar tensor representing the normalized weighted BCE loss.
31
- """
32
-
33
- if input.shape != target.shape:
34
- if input.shape[-1] == 1 and input.shape[:-1] == target.shape:
35
- input = input.squeeze(-1)
36
- elif target.shape[-1] == 1 and target.shape[:-1] == input.shape:
37
- target = target.squeeze(-1)
38
-
39
- # Compute per-element BCE loss (no reduction)
40
- loss = F.binary_cross_entropy_with_logits(input, target, reduction='none')
41
-
42
- # If weights not provided, use ones
43
- if weights is None:
44
- weights = torch.ones_like(loss)
45
-
46
- unique_labels = torch.unique(target)
47
- normalized_losses = []
48
- for label in unique_labels:
49
- label_mask = (target == label) # This will be a bool tensor
50
- # Defensive: make sure mask is bool
51
- if label_mask.dtype != torch.bool:
52
- label_mask = label_mask.bool()
53
- label_weights = weights[label_mask]
54
- label_losses = loss[label_mask]
55
- weight_sum = label_weights.sum()
56
- if weight_sum > 0:
57
- label_loss = (label_weights * label_losses).sum() / weight_sum
58
- normalized_losses.append(label_loss)
59
-
60
- if normalized_losses:
61
- return torch.stack(normalized_losses).mean()
62
- else:
63
- return torch.tensor(0.0, device=input.device)
64
-
65
-
66
- def roc_auc_score(classes : np.ndarray,
67
- predictions : np.ndarray,
68
- weights : np.ndarray = None) -> float:
69
- """
70
- Calculating ROC AUC score as the probability of correct ordering
71
- """
72
-
73
- if weights is None:
74
- weights = np.ones_like(predictions)
75
-
76
- assert len(classes) == len(predictions) == len(weights)
77
- assert classes.ndim == predictions.ndim == weights.ndim == 1
78
- class0, class1 = sorted(np.unique(classes))
79
-
80
- data = np.empty(
81
- shape=len(classes),
82
- dtype=[('c', classes.dtype),
83
- ('p', predictions.dtype),
84
- ('w', weights.dtype)]
85
- )
86
- data['c'], data['p'], data['w'] = classes, predictions, weights
87
-
88
- data = data[np.argsort(data['c'])]
89
- data = data[np.argsort(data['p'], kind='mergesort')] # here we're relying on stability as we need class orders preserved
90
-
91
- correction = 0.
92
- # mask1 - bool mask to highlight collision areas
93
- # mask2 - bool mask with collision areas' start points
94
- mask1 = np.empty(len(data), dtype=bool)
95
- mask2 = np.empty(len(data), dtype=bool)
96
- mask1[0] = mask2[-1] = False
97
- mask1[1:] = data['p'][1:] == data['p'][:-1]
98
- if mask1.any():
99
- mask2[:-1] = ~mask1[:-1] & mask1[1:]
100
- mask1[:-1] |= mask1[1:]
101
- ids, = mask2.nonzero()
102
- correction = sum([((dsplit['c'] == class0) * dsplit['w'] * msplit).sum() *
103
- ((dsplit['c'] == class1) * dsplit['w'] * msplit).sum()
104
- for dsplit, msplit in zip(np.split(data, ids), np.split(mask1, ids))]) * 0.5
105
-
106
- weights_0 = data['w'] * (data['c'] == class0)
107
- weights_1 = data['w'] * (data['c'] == class1)
108
- cumsum_0 = weights_0.cumsum()
109
-
110
- return ((cumsum_0 * weights_1).sum() - correction) / (weights_1.sum() * cumsum_0[-1])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/models/Edge_Network.py DELETED
@@ -1,72 +0,0 @@
1
- import torch
2
- import torch.nn as nn
3
- import dgl
4
-
5
- from models import utils
6
-
7
- class Edge_Network(nn.Module):
8
- def __init__(self, cfg):
9
- super().__init__()
10
- hid_size = cfg.hid_size
11
- n_layers = cfg.n_layers
12
- self.n_proc_steps = cfg.n_proc_steps
13
-
14
- #encoder
15
- self.node_encoder = utils.Make_MLP(cfg.input_dim_nodes, hid_size, hid_size, n_layers)
16
- self.edge_encoder = utils.Make_MLP(cfg.input_dim_edges, hid_size, hid_size, n_layers)
17
- self.global_encoder = utils.Make_MLP(cfg.input_dim_globals, hid_size, hid_size, n_layers)
18
-
19
- #GNN
20
- self.node_update = utils.Make_MLP(3*hid_size, hid_size, hid_size, n_layers)
21
- self.edge_update = utils.Make_MLP(4*hid_size, hid_size, hid_size, n_layers)
22
- self.global_update = utils.Make_MLP(3*hid_size, hid_size, hid_size, n_layers)
23
-
24
- #decoder
25
- self.global_decoder = utils.Make_MLP(hid_size, hid_size, hid_size, n_layers)
26
- self.classify = nn.Linear(hid_size, cfg.out_dim)
27
-
28
- def forward(self, node_feats, edge_feats, global_feats, batched_graph, metadata={}):
29
- # encoders
30
- batched_graph.ndata['h'] = self.node_encoder(node_feats)
31
- batched_graph.edata['e'] = self.edge_encoder(edge_feats)
32
-
33
- if global_feats.ndim == 3:
34
- global_feats = global_feats.view(-1, global_feats.shape[-1])
35
- h_global = self.global_encoder(global_feats)
36
-
37
- # message passing
38
- for _ in range(self.n_proc_steps):
39
- batched_graph.apply_edges(dgl.function.copy_u('h', 'm_u'))
40
- batched_graph.apply_edges(utils.copy_v)
41
-
42
- # edge update
43
- edge_inputs = torch.cat([
44
- batched_graph.edata['e'],
45
- batched_graph.edata['m_u'],
46
- batched_graph.edata['m_v'],
47
- utils.broadcast_global_to_edges(h_global, edge_split=metadata.get("batch_num_edges", None))
48
- ], dim=1)
49
- batched_graph.edata['e'] = self.edge_update(edge_inputs)
50
-
51
- # node update
52
- batched_graph.update_all(dgl.function.copy_e('e', 'm'), dgl.function.sum('m', 'h_e'))
53
- node_inputs = torch.cat([
54
- batched_graph.ndata['h'],
55
- batched_graph.ndata['h_e'],
56
- utils.broadcast_global_to_nodes(h_global, node_split=metadata.get("batch_num_nodes", None))
57
- ], dim=1)
58
- batched_graph.ndata['h'] = self.node_update(node_inputs)
59
-
60
- # global update
61
- graph_node_feat = utils.mean_nodes(
62
- batched_graph, 'h', node_split=metadata.get("batch_num_nodes", None)
63
- )
64
- graph_edge_feat = utils.mean_edges(
65
- batched_graph, 'e', edge_split=metadata.get("batch_num_edges", None)
66
- )
67
- h_global = self.global_update(torch.cat([h_global, graph_node_feat, graph_edge_feat], dim=1))
68
-
69
- h_global = self.global_decoder(h_global)
70
- out = self.classify(h_global)
71
- return out
72
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/models/MeshGraphNet.py DELETED
@@ -1,51 +0,0 @@
1
- import torch
2
- import torch.nn as nn
3
- import dgl
4
-
5
- from models import utils
6
-
7
- # Import the PhysicsNemo MeshGraphNet model
8
- from physicsnemo.models.meshgraphnet import MeshGraphNet as PhysicsNemoMeshGraphNet
9
-
10
- class MeshGraphNet(nn.Module):
11
- def __init__(self, cfg):
12
- super().__init__()
13
- base_gnn_cfg = cfg.base_gnn
14
- self.base_gnn = PhysicsNemoMeshGraphNet(**base_gnn_cfg)
15
-
16
- self.global_mlp = nn.Sequential(
17
- nn.Linear(cfg.global_feat_dim, cfg.global_emb_dim),
18
- nn.ReLU(),
19
- )
20
-
21
- self.mlp = nn.Linear(
22
- base_gnn_cfg['output_dim'] + base_gnn_cfg['input_dim_edges'] + cfg.global_emb_dim,
23
- cfg.out_dim
24
- )
25
-
26
- def forward(self, node_feats, edge_feats, global_feats, batched_graph, metadata={}):
27
- """
28
- node_feats: [total_num_nodes, node_feat_dim]
29
- edge_feats: [total_num_edges, edge_feat_dim]
30
- global_feats: [num_graphs, global_feat_dim]
31
- batched_graph: DGLGraph, representing the collection of graphs in a batch
32
- metadata: dict, may contain 'batch_num_nodes', 'batch_num_edges', etc.
33
- Returns:
34
- graph_pred: [num_graphs, out_dim]
35
- """
36
- node_pred = self.base_gnn(node_feats, edge_feats, batched_graph)
37
- batched_graph.ndata['h'] = node_pred
38
- batched_graph.edata['e'] = edge_feats
39
-
40
- graph_node_feat = utils.mean_nodes(batched_graph, 'h', node_split=metadata.get("batch_num_nodes", None))
41
- graph_edge_feat = utils.mean_edges(batched_graph, 'e', edge_split=metadata.get("batch_num_edges", None))
42
-
43
- # Flatten global_feats if needed
44
- if global_feats.ndim == 3:
45
- global_feats = global_feats.view(-1, global_feats.shape[-1])
46
- global_emb = self.global_mlp(global_feats) # [num_graphs, global_emb_dim]
47
-
48
- combined_feat = torch.cat([graph_node_feat, graph_edge_feat, global_emb], dim=-1)
49
- graph_pred = self.mlp(combined_feat)
50
- return graph_pred
51
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/models/utils.py DELETED
@@ -1,135 +0,0 @@
1
- import torch
2
- import torch.nn as nn
3
- import dgl
4
-
5
- def mean_nodes(batched_graph, feat_key='h', op='mean', node_split=None):
6
- """
7
- Aggregates node features per disjoint graph in a batched DGLGraph.
8
-
9
- Args:
10
- batched_graph: DGLGraph
11
- feat_key: str, node feature key
12
- op: 'mean', 'sum', or 'max'
13
- node_split: 1D tensor or list of ints (num nodes per graph)
14
-
15
- Returns:
16
- Tensor of shape [num_graphs, node_feat_dim]
17
- """
18
- h = batched_graph.ndata[feat_key]
19
- if node_split is None or len(node_split) == 0:
20
- if op == 'mean':
21
- return dgl.mean_nodes(batched_graph, feat_key)
22
- elif op == 'sum':
23
- return dgl.sum_nodes(batched_graph, feat_key)
24
- elif op == 'max':
25
- return dgl.max_nodes(batched_graph, feat_key)
26
- else:
27
- raise ValueError(f"Unknown op: {op}")
28
- else:
29
- # Ensure node_split is a flat list of ints
30
- if isinstance(node_split, torch.Tensor):
31
- splits = node_split.view(-1).tolist()
32
- else:
33
- splits = [int(x) for x in node_split]
34
- chunks = torch.split(h, splits, dim=0)
35
- if op == 'mean':
36
- out = torch.stack([chunk.mean(0) if chunk.shape[0] > 0 else torch.zeros_like(h[0]) for chunk in chunks])
37
- elif op == 'sum':
38
- out = torch.stack([chunk.sum(0) if chunk.shape[0] > 0 else torch.zeros_like(h[0]) for chunk in chunks])
39
- elif op == 'max':
40
- out = torch.stack([chunk.max(0).values if chunk.shape[0] > 0 else torch.zeros_like(h[0]) for chunk in chunks])
41
- else:
42
- raise ValueError(f"Unknown op: {op}")
43
- return out
44
-
45
- def mean_edges(batched_graph, feat_key='e', op='mean', edge_split=None):
46
- """
47
- Aggregates edge features per disjoint graph in a batched DGLGraph.
48
-
49
- Args:
50
- batched_graph: DGLGraph
51
- feat_key: str, edge feature key
52
- op: 'mean', 'sum', or 'max'
53
- edge_split: 1D tensor or list of ints (num edges per graph)
54
-
55
- Returns:
56
- Tensor of shape [num_graphs, edge_feat_dim]
57
- """
58
- e = batched_graph.edata[feat_key]
59
- if edge_split is None or len(edge_split) == 0:
60
- if op == 'mean':
61
- return dgl.mean_edges(batched_graph, feat_key)
62
- elif op == 'sum':
63
- return dgl.sum_edges(batched_graph, feat_key)
64
- elif op == 'max':
65
- return dgl.max_edges(batched_graph, feat_key)
66
- else:
67
- raise ValueError(f"Unknown op: {op}")
68
- else:
69
- # Ensure edge_split is a flat list of ints
70
- if isinstance(edge_split, torch.Tensor):
71
- splits = edge_split.view(-1).tolist()
72
- else:
73
- splits = [int(x) for x in edge_split]
74
- chunks = torch.split(e, splits, dim=0)
75
- if op == 'mean':
76
- out = torch.stack([chunk.mean(0) if chunk.shape[0] > 0 else torch.zeros_like(e[0]) for chunk in chunks])
77
- elif op == 'sum':
78
- out = torch.stack([chunk.sum(0) if chunk.shape[0] > 0 else torch.zeros_like(e[0]) for chunk in chunks])
79
- elif op == 'max':
80
- out = torch.stack([chunk.max(0).values if chunk.shape[0] > 0 else torch.zeros_like(e[0]) for chunk in chunks])
81
- else:
82
- raise ValueError(f"Unknown op: {op}")
83
- return out
84
-
85
- def Make_SLP(in_size, out_size, activation = nn.ReLU, dropout = 0):
86
- layers = []
87
- layers.append(nn.Linear(in_size, out_size))
88
- layers.append(activation())
89
- layers.append(nn.Dropout(dropout))
90
- return layers
91
-
92
- def Make_MLP(in_size, hid_size, out_size, n_layers, activation = nn.ReLU, dropout = 0):
93
- layers = []
94
- if n_layers > 1:
95
- layers += Make_SLP(in_size, hid_size, activation, dropout)
96
- for i in range(n_layers-2):
97
- layers += Make_SLP(hid_size, hid_size, activation, dropout)
98
- layers += Make_SLP(hid_size, out_size, activation, dropout)
99
- else:
100
- layers += Make_SLP(in_size, out_size, activation, dropout)
101
- layers.append(torch.nn.LayerNorm(out_size))
102
- return nn.Sequential(*layers)
103
-
104
- def broadcast_global_to_nodes(globals, node_split):
105
- """
106
- globals: [num_graphs, global_dim]
107
- node_split: list/1D tensor of length num_graphs, number of nodes per graph
108
- Returns: [total_num_nodes, global_dim]
109
- """
110
- if node_split is None:
111
- raise ValueError("node_split must be provided")
112
- if not torch.is_tensor(node_split):
113
- node_split = torch.tensor(node_split, dtype=torch.long, device=globals.device)
114
- else:
115
- node_split = node_split.to(device=globals.device, dtype=torch.long)
116
- node_split = node_split.flatten()
117
- return torch.repeat_interleave(globals, node_split, dim=0)
118
-
119
- def broadcast_global_to_edges(globals, edge_split):
120
- """
121
- globals: [num_graphs, global_dim] (on CUDA or CPU)
122
- edge_split: list/1D tensor of length num_graphs, number of edges per graph (CPU or CUDA)
123
- Returns: [total_num_edges, global_dim]
124
- """
125
- if edge_split is None:
126
- raise ValueError("edge_split must be provided")
127
- if not torch.is_tensor(edge_split):
128
- edge_split = torch.tensor(edge_split, dtype=torch.long, device=globals.device)
129
- else:
130
- edge_split = edge_split.to(device=globals.device, dtype=torch.long)
131
- edge_split = edge_split.flatten()
132
- return torch.repeat_interleave(globals, edge_split, dim=0)
133
-
134
- def copy_v(edges):
135
- return {'m_v': edges.dst['h']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/setup/Dockerfile DELETED
@@ -1,23 +0,0 @@
1
- FROM nvcr.io/nvidia/physicsnemo/physicsnemo:25.06
2
-
3
- WORKDIR /global/cfs/projectdirs/atlas/joshua/GNN4Colliders
4
-
5
- LABEL maintainer.name="Joshua Ho"
6
- LABEL maintainer.email="ho22joshua@berkeley.edu"
7
-
8
- ENV LANG=C.UTF-8
9
-
10
- # Install system dependencies: vim, OpenMPI, and build tools
11
- RUN apt-get update -qq \
12
- && apt-get install -y --no-install-recommends \
13
- wget lsb-release gnupg software-properties-common \
14
- vim \
15
- g++-11 gcc-11 libstdc++-11-dev \
16
- openmpi-bin openmpi-common libopenmpi-dev \
17
- && rm -rf /var/lib/apt/lists/*
18
-
19
- # Install Python packages: mpi4py and jupyter
20
- RUN pip install --no-cache-dir mpi4py jupyter uproot
21
-
22
- # (Optional) Expose Jupyter port
23
- EXPOSE 8888
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/setup/build_image.sh DELETED
@@ -1,4 +0,0 @@
1
- tag=$1
2
- echo $tag
3
- podman-hpc build -t joshuaho/nemo:$tag --platform linux/amd64 .
4
- podman-hpc migrate joshuaho/nemo:$tag
 
 
 
 
 
physicsnemo/train.py DELETED
@@ -1,246 +0,0 @@
1
- import time, os
2
-
3
- start = time.time()
4
- import torch
5
- from torch.nn.parallel import DistributedDataParallel
6
- from dgl.dataloading import GraphDataLoader
7
- from torch.amp import GradScaler
8
- import numpy as np
9
- import hydra
10
- from omegaconf import DictConfig
11
- from physicsnemo.launch.logging import (
12
- PythonLogger,
13
- RankZeroLoggingWrapper,
14
- )
15
- from physicsnemo.launch.utils import load_checkpoint, save_checkpoint
16
- from physicsnemo.distributed.manager import DistributedManager
17
-
18
- import json
19
- from tqdm import tqdm
20
- import random
21
-
22
- import models.MeshGraphNet as MeshGraphNet
23
- from dataset.Dataset import get_dataset
24
- import metrics
25
-
26
- import utils
27
-
28
- class MGNTrainer:
29
- def __init__(self, logger, cfg, dist):
30
- # set device
31
- self.device = dist.device
32
- logger.info(f"Using {self.device} device")
33
-
34
- start = time.time()
35
- self.trainloader, self.valloader, self.testloader = get_dataset(cfg, self.device)
36
- print(f"total time loading dataset: {time.time() - start:.2f} seconds")
37
-
38
- dtype_str = getattr(cfg.root_dataset, "dtype", "torch.float32")
39
- if isinstance(dtype_str, str) and dtype_str.startswith("torch."):
40
- self.dtype = getattr(torch, dtype_str.split(".")[-1], torch.float32)
41
- else:
42
- self.dtype = torch.float32
43
-
44
- self.model = utils.build_from_module(cfg.architecture)
45
- self.model = self.model.to(dtype=self.dtype, device=self.device)
46
- # num_params = sum(p.numel() for p in self.model.parameters() if p.requires_grad)
47
- # print(f"Number of trainable parameters: {num_params}")
48
-
49
- if cfg.performance.jit:
50
- self.model = torch.jit.script(self.model).to(self.device)
51
- else:
52
- self.model = self.model.to(self.device)
53
-
54
- # instantiate loss, optimizer, and scheduler
55
- self.optimizer = torch.optim.Adam(self.model.parameters(), lr=cfg.scheduler.lr)
56
- self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(
57
- self.optimizer,
58
- T_max=cfg.training.epochs,
59
- eta_min=cfg.scheduler.lr * cfg.scheduler.lr_decay,
60
- )
61
- self.scaler = GradScaler('cuda')
62
-
63
- # load checkpoint
64
- self.epoch_init = load_checkpoint(
65
- os.path.join(cfg.checkpoints.ckpt_path, cfg.checkpoints.ckpt_name),
66
- models=self.model,
67
- optimizer=self.optimizer,
68
- scheduler=self.scheduler,
69
- scaler=self.scaler,
70
- device=self.device,
71
- )
72
-
73
- self.cfg = cfg
74
-
75
- def backward(self, loss):
76
- """
77
- Perform backward pass.
78
-
79
- Arguments:
80
- loss: loss value.
81
-
82
- """
83
- # backward pass
84
- if self.cfg.performance.amp:
85
- self.scaler.scale(loss).backward()
86
- self.scaler.step(self.optimizer)
87
- self.scaler.update()
88
- else:
89
- loss.backward()
90
- self.optimizer.step()
91
-
92
- def train(self, graph, metadata):
93
- """
94
- Perform one training iteration over one graph. The training is performed
95
- over multiple timesteps, where the number of timesteps is specified in
96
- the 'stride' parameter.
97
-
98
- Arguments:
99
- graph: the desired graph.
100
-
101
- Returns:
102
- loss: loss value.
103
-
104
- """
105
- graph = graph.to(self.device, non_blocking=True)
106
- globals = metadata['globals'].to(self.device, non_blocking=True)
107
- label = metadata['label'].to(self.device, non_blocking=True)
108
- weight = metadata['weight'].to(self.device, non_blocking=True)
109
-
110
- self.optimizer.zero_grad()
111
- pred = self.model(graph.ndata["features"], graph.edata["features"], globals, graph, metadata)
112
- loss = metrics.weighted_bce(pred, label, weights=weight)
113
- self.backward(loss)
114
- return loss.detach()
115
-
116
- @torch.no_grad()
117
- def eval(self):
118
- """
119
- Evaluate the model on one batch.
120
-
121
- Args:
122
- graph (DGLGraph): The input graph.
123
- label (Tensor): The target labels.
124
-
125
- Returns:
126
- loss (Tensor): The computed loss value (scalar).
127
- """
128
- predictions = []
129
- labels = []
130
- weights = []
131
-
132
- for graph, metadata in self.valloader:
133
-
134
- graph = graph.to(self.device, non_blocking=True)
135
- globals = metadata['globals'].to(self.device, non_blocking=True)
136
- label = metadata['label'].to(self.device, non_blocking=True)
137
- weight = metadata['weight'].to(self.device, non_blocking=True)
138
-
139
- pred = self.model(graph.ndata["features"], graph.edata["features"], globals, graph, metadata)
140
- predictions.append(pred)
141
- labels.append(label)
142
- weights.append(weight)
143
-
144
- predictions = torch.cat(predictions, dim=0)
145
- labels = torch.cat(labels, dim=0)
146
- weights = torch.cat(weights, dim=0)
147
-
148
- loss = metrics.weighted_bce(predictions, labels, weights=weights)
149
-
150
- # Convert logits to probabilities
151
- prob = torch.sigmoid(predictions)
152
-
153
- # Flatten to 1D arrays
154
- prob_flat = prob.detach().to(torch.float32).cpu().numpy().flatten()
155
- labels_flat = labels.detach().to(torch.float32).cpu().numpy().flatten()
156
-
157
- # Calculate AUC
158
- try:
159
- auc = metrics.roc_auc_score(labels_flat, prob_flat)
160
- except ValueError:
161
- auc = float('nan') # Not enough classes present for AUC
162
-
163
- return loss, auc
164
-
165
- @hydra.main(version_base=None, config_path="./configs/", config_name="tHjb_CP_0_vs_45")
166
- def do_training(cfg: DictConfig):
167
- """
168
- Perform training over all graphs in the dataset.
169
-
170
- Arguments:
171
- cfg: Dictionary of parameters.
172
-
173
- """
174
- random.seed(cfg.random_seed)
175
- np.random.seed(cfg.random_seed)
176
- torch.manual_seed(cfg.random_seed)
177
-
178
- # initialize distributed manager
179
- DistributedManager.initialize()
180
- dist = DistributedManager()
181
-
182
- # initialize loggers
183
- os.makedirs(cfg.checkpoints.ckpt_path, exist_ok=True)
184
- logger = PythonLogger("main")
185
- logger.file_logging(os.path.join(cfg.checkpoints.ckpt_path, "train.log"))
186
-
187
- # initialize trainer
188
- trainer = MGNTrainer(logger, cfg, dist)
189
-
190
- if dist.distributed:
191
- ddps = torch.cuda.Stream()
192
- with torch.cuda.stream(ddps):
193
- trainer.model = DistributedDataParallel(
194
- trainer.model,
195
- device_ids=[dist.local_rank], # Set the device_id to be
196
- # the local rank of this process on
197
- # this node
198
- output_device=dist.device,
199
- broadcast_buffers=dist.broadcast_buffers,
200
- find_unused_parameters=dist.find_unused_parameters,
201
- )
202
- torch.cuda.current_stream().wait_stream(ddps)
203
-
204
- # training loop
205
- start = time.time()
206
- logger.info("Training started...")
207
- for epoch in range(trainer.epoch_init, cfg.training.epochs):
208
-
209
- # Training
210
- train_loss = []
211
- for graph, metadata in tqdm(trainer.trainloader, desc=f"epoch {epoch} trianing"):
212
- trainer.model.train()
213
- loss = trainer.train(graph, metadata)
214
- train_loss.append(loss.item())
215
-
216
- val_loss, val_auc = trainer.eval()
217
-
218
- train_loss = torch.tensor(train_loss).mean()
219
-
220
- logger.info(
221
- f"epoch: {epoch}, loss: {train_loss:10.3e}, val_loss: {val_loss:10.3e}, val_auc = {val_auc:10.3e}, time per epoch: {(time.time()-start):10.3e}"
222
- )
223
-
224
- # save checkpoint
225
- save_checkpoint(
226
- os.path.join(cfg.checkpoints.ckpt_path, cfg.checkpoints.ckpt_name),
227
- models=trainer.model,
228
- optimizer=trainer.optimizer,
229
- scheduler=trainer.scheduler,
230
- scaler=trainer.scaler,
231
- epoch=epoch,
232
- )
233
- start = time.time()
234
- trainer.scheduler.step()
235
- logger.info("Training completed!")
236
-
237
-
238
- """
239
- Perform training over all graphs in the dataset.
240
-
241
- Arguments:
242
- cfg: Dictionary of parameters.
243
-
244
- """
245
- if __name__ == "__main__":
246
- do_training()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
physicsnemo/utils.py DELETED
@@ -1,11 +0,0 @@
1
- import importlib
2
- from types import SimpleNamespace
3
-
4
- def build_from_module(cfg):
5
- modname = cfg['module']
6
- classname = cfg['class']
7
- args = cfg['args']
8
- module = importlib.import_module(modname)
9
- model_cls = getattr(module, classname)
10
- cfg_obj = SimpleNamespace(**args)
11
- return model_cls(cfg_obj)
 
 
 
 
 
 
 
 
 
 
 
 
root_gnn_dgl/README.md CHANGED
@@ -1,68 +1,53 @@
1
-
2
  # root_gnn_dgl
3
 
4
- Pretrained DGL-based ROOT graph neural network.
 
 
 
 
 
 
5
 
6
- Pretrained model location: `/global/cfs/projectdirs/atlas/joshua/Pretrained_GNN/multiclass_pretrained_model_12/`
7
- To use the pretrained model, take a look at a finetuning config in `configs`.
8
- Replace `pretraining_path:` with `/global/cfs/projectdirs/atlas/joshua/Pretrained_GNN/multiclass_pretrained_model_12/model_epoch_71.pt`.
9
 
10
- ## Overview
11
- - Stable release with pretrained model weights.
12
 
13
- ## Conda setup
 
14
 
15
- The conda environment is required for the inference step: applying the GNN onto root files and saving GNN scores as an additional branch. This is because the infereces script uses pyROOT.
 
16
 
 
 
17
  ```bash
18
- cd setup
19
- conda env create -f environment.yml
20
- conda activate pytorch
21
- cd ..
22
- python setup/test_setup.py
23
  ```
24
-
25
- ## Container Setup (Podman-HPC)
26
-
27
- - NERSC Perlmutter environment with `podman-hpc` available.
28
- - Access to `joshuaho/pytorch:1.0` on Docker Hub [https://hub.docker.com/r/joshuaho/pytorch](https://hub.docker.com/r/joshuaho/pytorch)
29
-
30
- The inference step requires the conda environment, since the container does not contain ROOT.
31
-
32
- ### Pull the Prebuilt Image
33
-
34
  ```bash
35
- podman-hpc pull docker.io/joshuaho/pytorch:1.0
36
  ```
37
 
38
- Or, you can build your own container here:
39
-
40
  ```bash
41
- cd setup
42
- source build_image.sh
43
  ```
44
 
45
- Run the image and mount the paths you need, replaceing `<source>` with source directory path and `<target>` with the path for when you are inside the container.
 
46
  ```bash
 
 
 
47
 
48
- podman-hpc run \
49
- -it \
50
- --mount type=bind,source=<source>,target=<target> \
51
- --rm \
52
- --network host \
53
- --gpu \
54
- --userns keep-id \
55
- --shm-size=32g \
56
- joshuaho/pytorch:1.0
57
- ```
58
-
59
- ### Test the Environment
60
  Run the `setup/test_setup.py` script to confirm that all packages needed for training are properly set up.
61
  ```bash
62
  python setup/test_setup.py
63
  ```
64
-
65
-
66
  ## Running the Demo
67
  The demo training is an example of our ML workflow, consisting of training a pretrained model, then finetuning it for an analysis task, while also training a model for the analysis task from scratch. The config files for the demo are located in the directory `configs/stats_100K/`. The demo can be run on a login node on Perlmutter (if enough GPU memory is availble).
68
 
@@ -122,16 +107,16 @@ Inference is done by `scripts/inference.py`. This script applies the model defin
122
 
123
  ```bash
124
  python scripts/inference.py \
125
- --target "/global/cfs/projectdirs/atlas/joshua/gnn_data/stats_100K/ttH_NLO.root" \
126
- --destination "/global/cfs/projectdirs/atlas/joshua/gnn_data/scores/stats_100K/ttH_NLO.root" \
127
  --config "configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml" \
128
- --branch_name "GNN_Score" \
129
  --chunks 1 \
130
  --chunkno 0 \
131
- --write
 
132
  ```
133
 
134
- You can also input a list as the `--config` and the `--branch_name` to simultaneously apply multiple models onto the same set of samples. An example on how to do this in shell script is in the `run_demo.sh` file.
135
 
136
  ## Running Jobs + Parallelization
137
 
 
 
1
  # root_gnn_dgl
2
 
3
+ ## Data Directory (for Hackathon)
4
+ `/global/cfs/projectdirs/trn007/lbl_atlas/data/`
5
+
6
+ * `stats_all`: full statistics sample, ~10M events per process
7
+ * `stats_100K`: reduced statistics sample, 100K events per process
8
+ * `processed_graphs`: graphs that have already been processed
9
+ * `scores`: a copy of the samples along with the GNN scores for each event
10
 
11
+ ## Environment Setup
 
 
12
 
13
+ The environment dependencies for this project are listed in `setup/environment.yml`. Follow the steps below to set up the environment:
 
14
 
15
+ ### Step 1: Install Conda
16
+ If you don’t already have Conda installed, install either Miniconda (lightweight) or Anaconda (full version):
17
 
18
+ - **Miniconda**: Download and install from [https://docs.conda.io/en/latest/miniconda.html](https://docs.conda.io/en/latest/miniconda.html).
19
+ - **Anaconda**: Download and install from [https://www.anaconda.com/products/distribution](https://www.anaconda.com/products/distribution).
20
 
21
+ ### Step 2: Clone the Repository
22
+ Clone this repository to your local machine:
23
  ```bash
24
+ git init
25
+ git lfs install
26
+ git clone https://huggingface.co/HWresearch/GNN4Colliders
 
 
27
  ```
28
+ If you want to clone without large files - just their pointers
 
 
 
 
 
 
 
 
 
29
  ```bash
30
+ GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/HWresearch/GNN4Colliders
31
  ```
32
 
33
+ ### Step 3: Create the Conda Environment
34
+ Use the `environment.yml` file to create the Conda environment:
35
  ```bash
36
+ conda env create -f setup/environment.yml -n <environment_name>
 
37
  ```
38
 
39
+ ### Step 4: Activate the Environment
40
+ Activate the newly created environment:
41
  ```bash
42
+ conda activate <environment_name>
43
+ ```
44
+ Replace <environment_name> with the name of the environment specified in Step 4.
45
 
46
+ ### Step 5: Test the Environment
 
 
 
 
 
 
 
 
 
 
 
47
  Run the `setup/test_setup.py` script to confirm that all packages needed for training are properly set up.
48
  ```bash
49
  python setup/test_setup.py
50
  ```
 
 
51
  ## Running the Demo
52
  The demo training is an example of our ML workflow, consisting of training a pretrained model, then finetuning it for an analysis task, while also training a model for the analysis task from scratch. The config files for the demo are located in the directory `configs/stats_100K/`. The demo can be run on a login node on Perlmutter (if enough GPU memory is availble).
53
 
 
107
 
108
  ```bash
109
  python scripts/inference.py \
110
+ --target "/global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/ttH_NLO.root" \
111
+ --destination "/global/cfs/projectdirs/trn007/lbl_atlas/data/scores/stats_100K/ttH_NLO.root" \
112
  --config "configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml" \
 
113
  --chunks 1 \
114
  --chunkno 0 \
115
+ --write \
116
+ --branch 'GNN_Score'
117
  ```
118
 
119
+ You can also input a list as the `--config` and the `--branch` to simultaneously apply multiple models onto the same set of samples. An example on how to do this in shell script is in the `run_demo.sh` file.
120
 
121
  ## Running Jobs + Parallelization
122
 
root_gnn_dgl/configs/attention/ttH_CP_even_vs_odd.yaml ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd
2
+ Training_Directory: trainings/attention/ttH_CP_even_vs_odd
3
+ Model:
4
+ module: models.GCN
5
+ class: Attention_Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ num_heads: 2
14
+ Training:
15
+ epochs: 500
16
+ batch_size: 1024
17
+ learning_rate: 0.0001
18
+ gamma: 0.99
19
+ Datasets:
20
+ ttH_CP_even: &dataset_defn
21
+ module: root_gnn_base.dataset
22
+ class: LazyDataset
23
+ shuffle_chunks: 3
24
+ batch_size: 1024
25
+ padding_mode: NODE
26
+ args: &dataset_args
27
+ name: ttH_CP_even
28
+ label: 0
29
+ # weight_var: weight
30
+ chunks: 3
31
+ buffer_size: 2
32
+ file_names: ttH_NLO.root
33
+ tree_name: output
34
+ fold_var: Number
35
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
36
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/attention/ttH_CP_even_vs_odd/
37
+ node_branch_names:
38
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
39
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
40
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
41
+ - CALC_E
42
+ - [jet_btag, 0, 0, 0, 0]
43
+ - [0, ele_charge, mu_charge, 0, 0]
44
+ - NODE_TYPE
45
+ node_branch_types: [vector, vector, vector, vector, single]
46
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
47
+ folding:
48
+ n_folds: 4
49
+ test: [0]
50
+ # validation: 1
51
+ train: [1, 2, 3]
52
+ ttH_CP_odd:
53
+ <<: *dataset_defn
54
+ args:
55
+ <<: *dataset_args
56
+ name: ttH_CP_odd
57
+ label: 1
58
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml CHANGED
@@ -41,8 +41,8 @@ Datasets:
41
  file_names: ttH_NLO.root
42
  tree_name: output
43
  fold_var: Number
44
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_100K/
45
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_100K/ttH_CP_even_vs_odd/
46
  node_branch_names:
47
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
48
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
41
  file_names: ttH_NLO.root
42
  tree_name: output
43
  fold_var: Number
44
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
45
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/ttH_CP_even_vs_odd/
46
  node_branch_names:
47
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
48
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_100K/pretraining_multiclass.yaml CHANGED
@@ -38,8 +38,8 @@ Datasets:
38
  file_names: ttH_NLO_inc.root
39
  tree_name: output
40
  fold_var: Number
41
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_100K/
42
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_100K/pretraining_multiclass/
43
  node_branch_names:
44
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
45
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
38
  file_names: ttH_NLO_inc.root
39
  tree_name: output
40
  fold_var: Number
41
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
42
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/pretraining_multiclass/
43
  node_branch_names:
44
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
45
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd.yaml CHANGED
@@ -31,8 +31,8 @@ Datasets:
31
  file_names: ttH_NLO.root
32
  tree_name: output
33
  fold_var: Number
34
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_100K/
35
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_100K/ttH_CP_even_vs_odd/
36
  node_branch_names:
37
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
31
  file_names: ttH_NLO.root
32
  tree_name: output
33
  fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/ttH_CP_even_vs_odd/
36
  node_branch_names:
37
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_2048.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_2048
2
+ Training_Directory: trainings/stats_100K/ttH_CP_even_vs_odd_batch_size_2048
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 2048
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 3
23
+ batch_size: 2048
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 3
30
+ buffer_size: 2
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/ttH_CP_even_vs_odd_batch_size_2048/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_4096.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_4096
2
+ Training_Directory: trainings/stats_100K/ttH_CP_even_vs_odd_batch_size_4096
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 1024
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 3
23
+ batch_size: 4096
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 3
30
+ buffer_size: 2
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/ttH_CP_even_vs_odd_batch_size_4096/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_100K/ttH_CP_even_vs_odd_batch_size_8192.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_8192
2
+ Training_Directory: trainings/stats_100K/ttH_CP_even_vs_odd_batch_size_8192
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 2048
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 3
23
+ batch_size: 2048
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 3
30
+ buffer_size: 2
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_100K/ttH_CP_even_vs_odd_batch_size_8192/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_all/finetuning_ttH_CP_even_vs_odd.yaml CHANGED
@@ -41,8 +41,8 @@ Datasets:
41
  file_names: ttH_NLO.root
42
  tree_name: output
43
  fold_var: Number
44
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_all/
45
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_all/ttH_CP_even_vs_odd/
46
  node_branch_names:
47
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
48
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
41
  file_names: ttH_NLO.root
42
  tree_name: output
43
  fold_var: Number
44
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
45
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/ttH_CP_even_vs_odd/
46
  node_branch_names:
47
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
48
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_all/pretraining_multiclass.yaml CHANGED
@@ -38,8 +38,8 @@ Datasets:
38
  file_names: ttH_NLO_inc.root
39
  tree_name: output
40
  fold_var: Number
41
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_all/
42
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_all/pretraining_multiclass/
43
  node_branch_names:
44
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
45
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
38
  file_names: ttH_NLO_inc.root
39
  tree_name: output
40
  fold_var: Number
41
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
42
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/pretraining_multiclass/
43
  node_branch_names:
44
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
45
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd.yaml CHANGED
@@ -31,8 +31,8 @@ Datasets:
31
  file_names: ttH_NLO.root
32
  tree_name: output
33
  fold_var: Number
34
- raw_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/stats_all/
35
- save_dir: /global/cfs/projectdirs/atlas/joshua/gnn_data/processed_graphs/stats_all/ttH_CP_even_vs_odd/
36
  node_branch_names:
37
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
 
31
  file_names: ttH_NLO.root
32
  tree_name: output
33
  fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/ttH_CP_even_vs_odd/
36
  node_branch_names:
37
  - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
  - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_2048.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_2048
2
+ Training_Directory: trainings/stats_all/ttH_CP_even_vs_odd_batch_size_2048
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 2048
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 10
23
+ batch_size: 2048
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 10
30
+ buffer_size: 3
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/ttH_CP_even_vs_odd_batch_size_2048/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_4096.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_4096
2
+ Training_Directory: trainings/stats_all/ttH_CP_even_vs_odd_batch_size_4096
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 4096
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 10
23
+ batch_size: 4096
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 10
30
+ buffer_size: 3
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/ttH_CP_even_vs_odd_batch_size_4096/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/configs/stats_all/ttH_CP_even_vs_odd_batch_size_8192.yaml ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Training_Name: ttH_CP_even_vs_odd_batch_size_8192
2
+ Training_Directory: trainings/stats_all/ttH_CP_even_vs_odd_batch_size_8192
3
+ Model:
4
+ module: models.GCN
5
+ class: Edge_Network
6
+ args:
7
+ hid_size: 64
8
+ in_size: 7
9
+ out_size: 1
10
+ n_layers: 4
11
+ n_proc_steps: 4
12
+ dropout: 0
13
+ Training:
14
+ epochs: 500
15
+ batch_size: 8192
16
+ learning_rate: 0.0001
17
+ gamma: 0.99
18
+ Datasets:
19
+ ttH_CP_even: &dataset_defn
20
+ module: root_gnn_base.dataset
21
+ class: LazyDataset
22
+ shuffle_chunks: 10
23
+ batch_size: 8192
24
+ padding_mode: NONE #one of STEPS, FIXED, or NONE
25
+ args: &dataset_args
26
+ name: ttH_CP_even
27
+ label: 0
28
+ # weight_var: weight
29
+ chunks: 10
30
+ buffer_size: 3
31
+ file_names: ttH_NLO.root
32
+ tree_name: output
33
+ fold_var: Number
34
+ raw_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/stats_all/
35
+ save_dir: /global/cfs/projectdirs/trn007/lbl_atlas/data/processed_graphs/stats_all/ttH_CP_even_vs_odd_batch_size_8192/
36
+ node_branch_names:
37
+ - [jet_pt, ele_pt, mu_pt, ph_pt, MET_met]
38
+ - [jet_eta, ele_eta, mu_eta, ph_eta, 0]
39
+ - [jet_phi, ele_phi, mu_phi, ph_phi, MET_phi]
40
+ - CALC_E
41
+ - [jet_btag, 0, 0, 0, 0]
42
+ - [0, ele_charge, mu_charge, 0, 0]
43
+ - NODE_TYPE
44
+ node_branch_types: [vector, vector, vector, vector, single]
45
+ node_feature_scales: [1e-1, 1, 1, 1e-1, 1, 1, 1]
46
+ folding:
47
+ n_folds: 4
48
+ test: [0]
49
+ # validation: 1
50
+ train: [1, 2, 3]
51
+ ttH_CP_odd:
52
+ <<: *dataset_defn
53
+ args:
54
+ <<: *dataset_args
55
+ name: ttH_CP_odd
56
+ label: 1
57
+ file_names: ttH_CPodd.root
root_gnn_dgl/jobs/interactive.sh CHANGED
@@ -1 +1 @@
1
- salloc --nodes 1 --qos shared_interactive --time 04:00:00 --constraint gpu --account=atlas --gres=gpu:1
 
1
+ salloc --nodes 1 --qos shared_interactive --time 04:00:00 --constraint gpu --account=trn007 --gres=gpu:1
root_gnn_dgl/run_demo.sh CHANGED
@@ -31,7 +31,7 @@ python scripts/training_script.py --config configs/stats_100K/ttH_CP_even_vs_odd
31
 
32
  python scripts/training_script.py --config configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml --preshuffle --nocompile --lazy
33
 
34
- # Inference: Writing GNN Scores for from-scratch training and finetuned training to root files
35
  files=(
36
  "ttH_NLO.root"
37
  "ttH_CPodd.root"
@@ -50,8 +50,8 @@ branch_name=(
50
  for ((j=0; j<${#files[@]}; j++))
51
  do
52
  python scripts/inference.py \
53
- --target "/global/cfs/projectdirs/atlas/joshua/gnn_data/stats_100K/${files[j]}" \
54
- --destination "/global/cfs/projectdirs/atlas/joshua/gnn_data/scores/stats_100K/${files[j]}" \
55
  --config "${config[@]}" \
56
  --branch_name "${branch_name[@]}" \
57
  --chunks 1 \
 
31
 
32
  python scripts/training_script.py --config configs/stats_100K/finetuning_ttH_CP_even_vs_odd.yaml --preshuffle --nocompile --lazy
33
 
34
+ # Inference
35
  files=(
36
  "ttH_NLO.root"
37
  "ttH_CPodd.root"
 
50
  for ((j=0; j<${#files[@]}; j++))
51
  do
52
  python scripts/inference.py \
53
+ --target "/global/cfs/projectdirs/trn007/lbl_atlas/data/stats_100K/${files[j]}" \
54
+ --destination "/global/cfs/projectdirs/trn007/lbl_atlas/data/scores/stats_100K/${files[j]}" \
55
  --config "${config[@]}" \
56
  --branch_name "${branch_name[@]}" \
57
  --chunks 1 \
root_gnn_dgl/scripts/inference.py CHANGED
@@ -1,5 +1,6 @@
1
  import sys
2
- file_path = "/global/cfs/projectdirs/atlas/joshua/root_gnn/root_gnn_dgl"
 
3
  sys.path.append(file_path)
4
  import os
5
  import argparse
@@ -134,7 +135,6 @@ def main():
134
 
135
  import time
136
  start = time.time()
137
- import ROOT
138
  import torch
139
  from array import array
140
  import numpy as np
@@ -186,7 +186,6 @@ def main():
186
  lend = time.time()
187
  print('Loader finished in {:.2f} seconds'.format(lend - lstart))
188
  sample_graph, _, _, global_sample = loader[0]
189
- global_sample = []
190
 
191
  print('dset length =', len(dset))
192
  print('loader length =', len(loader))
@@ -198,7 +197,6 @@ def main():
198
  for config_file, branch in zip(args.config, args.branch_name):
199
  config = load_config(config_file)
200
  model = utils.buildFromConfig(config['Model'], {'sample_graph' : sample_graph, 'sample_global': global_sample}).to(device)
201
-
202
  if args.ckpt < 0:
203
  ep, checkpoint = utils.get_best_epoch(config, var=args.var, mode='max', device=device)
204
  else:
@@ -248,55 +246,41 @@ def main():
248
  all_labels[branch] = labels
249
  all_tracking[branch] = tracking_info
250
 
251
- if args.write:
252
- from ROOT import std
253
- # Open the original ROOT file
254
- infile = ROOT.TFile.Open(args.target)
255
- tree = infile.Get(dset_config['args']['tree_name'])
256
 
257
- # Create the destination directory if it doesn't exist
258
- os.makedirs(os.path.split(args.destination)[0], exist_ok=True)
 
259
 
260
- # Create a new ROOT file to write the modified tree
261
- outfile = ROOT.TFile.Open(args.destination, 'RECREATE')
 
262
 
263
- # Clone the original tree structure
264
- outtree = tree.CloneTree(0)
265
 
266
- # Create branches for all scores
267
- branch_vectors = {}
 
268
  for branch, scores in all_scores.items():
269
- if isinstance(scores[0], (list, tuple, np.ndarray)) and len(scores[0]) > 1:
270
- # Create a new branch for vectors
271
- branch_vectors[branch] = std.vector('float')()
272
- outtree.Branch(branch, branch_vectors[branch])
273
- else:
274
- # Create a new branch for single floats
275
- branch_vectors[branch] = array('f', [0])
276
- outtree.Branch(branch, branch_vectors[branch], f'{branch}/F')
277
-
278
- # Fill the tree
279
- for i in range(tree.GetEntries()):
280
- tree.GetEntry(i)
281
-
282
- for branch, scores in all_scores.items():
283
- branch_data = branch_vectors[branch]
284
- if isinstance(branch_data, array): # Check if it's a single float array
285
- branch_data[0] = float(scores[i])
286
- else: # Assume it's a std::vector<float>
287
- branch_data.clear()
288
- for value in scores[i]:
289
- branch_data.push_back(float(value))
290
-
291
- outtree.Fill()
292
-
293
- # Write the modified tree to the new file
294
- print(f'Writing to file {args.destination}')
295
- print(f'Input entries: {tree.GetEntries()}, Output entries: {outtree.GetEntries()}')
296
- print(f'Wrote scores to {args.branch_name}')
297
- outtree.Write()
298
- outfile.Close()
299
- infile.Close()
300
  else:
301
  os.makedirs(os.path.split(args.destination)[0], exist_ok=True)
302
  np.savez(args.destination, scores=all_scores, labels=all_labels, tracking_info=all_tracking)
 
1
  import sys
2
+ import os
3
+ file_path = os.getcwd()
4
  sys.path.append(file_path)
5
  import os
6
  import argparse
 
135
 
136
  import time
137
  start = time.time()
 
138
  import torch
139
  from array import array
140
  import numpy as np
 
186
  lend = time.time()
187
  print('Loader finished in {:.2f} seconds'.format(lend - lstart))
188
  sample_graph, _, _, global_sample = loader[0]
 
189
 
190
  print('dset length =', len(dset))
191
  print('loader length =', len(loader))
 
197
  for config_file, branch in zip(args.config, args.branch_name):
198
  config = load_config(config_file)
199
  model = utils.buildFromConfig(config['Model'], {'sample_graph' : sample_graph, 'sample_global': global_sample}).to(device)
 
200
  if args.ckpt < 0:
201
  ep, checkpoint = utils.get_best_epoch(config, var=args.var, mode='max', device=device)
202
  else:
 
246
  all_labels[branch] = labels
247
  all_tracking[branch] = tracking_info
248
 
 
 
 
 
 
249
 
250
+ if args.write:
251
+ import uproot
252
+ import awkward as ak
253
 
254
+ # Open the original ROOT file and get the tree
255
+ infile = uproot.open(args.target)
256
+ tree = infile[dset_config['args']['tree_name']]
257
 
258
+ # Read the original tree as an awkward array
259
+ original_data = tree.arrays(library="ak")
260
 
261
+ # Prepare new branches as dicts of arrays
262
+ new_branches = {}
263
+ n_entries = len(original_data)
264
  for branch, scores in all_scores.items():
265
+ # Ensure the scores array is the right length
266
+ scores = np.asarray(scores)
267
+ if scores.shape[0] != n_entries:
268
+ raise ValueError(f"Branch '{branch}' has {scores.shape[0]} entries, but tree has {n_entries}")
269
+ new_branches[branch] = scores
270
+
271
+ # Merge all arrays (original + new branches)
272
+ # Convert awkward to dict of numpy arrays for uproot
273
+ out_dict = {k: np.asarray(v) for k, v in ak.to_numpy(original_data).items()}
274
+ out_dict.update(new_branches)
275
+
276
+ # Write to new ROOT file
277
+ os.makedirs(os.path.split(args.destination)[0], exist_ok=True)
278
+ with uproot.recreate(args.destination) as outfile:
279
+ outfile.mktree(dset_config['args']['tree_name'], {k: v.dtype for k, v in out_dict.items()})
280
+ outfile[dset_config['args']['tree_name']].extend(out_dict)
281
+
282
+ print(f"Wrote new ROOT file {args.destination} with new branches {list(new_branches.keys())}")
283
+
 
 
 
 
 
 
 
 
 
 
 
 
284
  else:
285
  os.makedirs(os.path.split(args.destination)[0], exist_ok=True)
286
  np.savez(args.destination, scores=all_scores, labels=all_labels, tracking_info=all_tracking)
root_gnn_dgl/setup/Dockerfile CHANGED
@@ -1,22 +1,25 @@
1
  FROM nvcr.io/nvidia/dgl:25.05-py3
2
 
3
- WORKDIR /workspace
4
 
5
  LABEL maintainer.name="Joshua Ho"
6
  LABEL maintainer.email="ho22joshua@berkeley.edu"
7
 
8
  ENV LANG=C.UTF-8
9
 
10
- # System deps (with CA certs for HTTPS downloads)
11
  RUN apt-get update -qq \
12
  && apt-get install -y --no-install-recommends \
13
- wget curl ca-certificates lsb-release gnupg software-properties-common \
14
  vim \
15
  g++-11 gcc-11 libstdc++-11-dev \
16
  openmpi-bin openmpi-common libopenmpi-dev \
17
  && rm -rf /var/lib/apt/lists/*
18
 
19
- # Python packages
20
  RUN pip install --no-cache-dir mpi4py jupyter uproot
21
 
22
- EXPOSE 8888
 
 
 
 
1
  FROM nvcr.io/nvidia/dgl:25.05-py3
2
 
3
+ WORKDIR /global/cfs/projectdirs/atlas/joshua/GNN4Colliders
4
 
5
  LABEL maintainer.name="Joshua Ho"
6
  LABEL maintainer.email="ho22joshua@berkeley.edu"
7
 
8
  ENV LANG=C.UTF-8
9
 
10
+ # Install system dependencies: vim, OpenMPI, and build tools
11
  RUN apt-get update -qq \
12
  && apt-get install -y --no-install-recommends \
13
+ wget lsb-release gnupg software-properties-common \
14
  vim \
15
  g++-11 gcc-11 libstdc++-11-dev \
16
  openmpi-bin openmpi-common libopenmpi-dev \
17
  && rm -rf /var/lib/apt/lists/*
18
 
19
+ # Install Python packages: mpi4py and jupyter
20
  RUN pip install --no-cache-dir mpi4py jupyter uproot
21
 
22
+ # (Optional) Expose Jupyter port
23
+ EXPOSE 8888
24
+
25
+
root_gnn_dgl/setup/build_image.sh CHANGED
@@ -1,2 +1,4 @@
1
- podman-hpc build -t joshuaho/pytorch:1.0 --platform linux/amd64 .
2
- podman-hpc migrate joshuaho/pytorch:1.0
 
 
 
1
+ tag=$1
2
+ echo $tag
3
+ podman-hpc build -t joshuaho/pytorch:$tag --platform linux/amd64 .
4
+ podman-hpc migrate joshuaho/pytorch:$tag
root_gnn_dgl/setup/environment.yml CHANGED
@@ -1,4 +1,4 @@
1
- name: pytorch
2
  channels:
3
  - pytorch
4
  - dglteam/label/cu118
@@ -387,4 +387,5 @@ dependencies:
387
  - triton==2.3.0
388
  - typing-extensions==4.11.0
389
  - tzdata==2024.1
390
- - uproot==5.3.7
 
 
1
+ name: dgl
2
  channels:
3
  - pytorch
4
  - dglteam/label/cu118
 
387
  - triton==2.3.0
388
  - typing-extensions==4.11.0
389
  - tzdata==2024.1
390
+ - uproot==5.3.7
391
+ prefix: /global/homes/j/joshuaho/.conda/envs/dgl
root_gnn_dgl/setup/environment_torch24.yaml ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: pytorch_dgl_cf
2
+ channels:
3
+ - conda-forge
4
+ dependencies:
5
+ - _libgcc_mutex=0.1=conda_forge
6
+ - _openmp_mutex=4.5=3_kmp_llvm
7
+ - absl-py=2.3.1=pyhd8ed1ab_0
8
+ - annotated-types=0.7.0=pyhd8ed1ab_1
9
+ - astunparse=1.6.3=pyhd8ed1ab_3
10
+ - brotli-python=1.1.0=py310hf71b8c6_3
11
+ - bzip2=1.0.8=h4bc722e_7
12
+ - c-ares=1.34.5=hb9d3cd8_0
13
+ - ca-certificates=2025.7.14=hbd8a1cb_0
14
+ - cached-property=1.5.2=hd8ed1ab_1
15
+ - cached_property=1.5.2=pyha770c72_1
16
+ - certifi=2025.7.14=pyhd8ed1ab_0
17
+ - cffi=1.17.1=py310h8deb56e_0
18
+ - charset-normalizer=3.4.2=pyhd8ed1ab_0
19
+ - colorama=0.4.6=pyhd8ed1ab_1
20
+ - cpython=3.10.18=py310hd8ed1ab_0
21
+ - cuda-version=11.8=h70ddcb2_3
22
+ - cudatoolkit=11.8.0=h4ba93d1_13
23
+ - cudnn=8.9.7.29=hbc23b4c_3
24
+ - dgl=2.3.0=cuda118py310h5c70fa1_0
25
+ - filelock=3.18.0=pyhd8ed1ab_0
26
+ - flatbuffers=24.3.25=h59595ed_0
27
+ - fsspec=2025.7.0=pyhd8ed1ab_0
28
+ - gast=0.6.0=pyhd8ed1ab_0
29
+ - giflib=5.2.2=hd590300_0
30
+ - gmp=6.3.0=hac33072_2
31
+ - gmpy2=2.2.1=py310he8512ff_0
32
+ - google-pasta=0.2.0=pyhd8ed1ab_2
33
+ - grpcio=1.62.2=py310h1b8f574_0
34
+ - h2=4.2.0=pyhd8ed1ab_0
35
+ - h5py=3.14.0=nompi_py310hea1e86d_100
36
+ - hdf5=1.14.6=nompi_h6e4c0c1_102
37
+ - hpack=4.1.0=pyhd8ed1ab_0
38
+ - hyperframe=6.1.0=pyhd8ed1ab_0
39
+ - icu=75.1=he02047a_0
40
+ - idna=3.10=pyhd8ed1ab_1
41
+ - importlib-metadata=8.7.0=pyhe01879c_1
42
+ - jinja2=3.1.6=pyhd8ed1ab_0
43
+ - keras=3.10.0=pyh753f3f9_0
44
+ - kernel-headers_linux-64=4.18.0=he073ed8_8
45
+ - keyutils=1.6.1=h166bdaf_0
46
+ - krb5=1.21.3=h659f571_0
47
+ - ld_impl_linux-64=2.44=h1423503_1
48
+ - libabseil=20240116.2=cxx17_he02047a_1
49
+ - libaec=1.1.4=h3f801dc_0
50
+ - libblas=3.9.0=32_h59b9bed_openblas
51
+ - libcblas=3.9.0=32_he106b2a_openblas
52
+ - libcurl=8.14.1=h332b0f4_0
53
+ - libedit=3.1.20250104=pl5321h7949ede_0
54
+ - libev=4.33=hd590300_2
55
+ - libexpat=2.7.0=h5888daf_0
56
+ - libffi=3.4.6=h2dba641_1
57
+ - libgcc=15.1.0=h767d61c_3
58
+ - libgcc-ng=15.1.0=h69a702a_3
59
+ - libgfortran=15.1.0=h69a702a_3
60
+ - libgfortran5=15.1.0=hcea5267_3
61
+ - libgomp=15.1.0=h767d61c_3
62
+ - libgrpc=1.62.2=h15f2491_0
63
+ - libhwloc=2.11.2=default_h3d81e11_1002
64
+ - libiconv=1.18=h4ce23a2_1
65
+ - libjpeg-turbo=3.1.0=hb9d3cd8_0
66
+ - liblapack=3.9.0=32_h7ac8fdf_openblas
67
+ - liblapacke=3.9.0=32_he2f377e_openblas
68
+ - liblzma=5.8.1=hb9d3cd8_2
69
+ - libmagma=2.7.2=h09b5827_2
70
+ - libmagma_sparse=2.7.2=h09b5827_3
71
+ - libnghttp2=1.64.0=h161d5f1_0
72
+ - libnsl=2.0.1=hb9d3cd8_1
73
+ - libopenblas=0.3.30=pthreads_h94d23a6_0
74
+ - libpng=1.6.50=h943b412_0
75
+ - libprotobuf=4.25.3=hd5b35b9_1
76
+ - libre2-11=2023.09.01=h5a48ba9_2
77
+ - libsqlite=3.50.2=hee844dc_2
78
+ - libssh2=1.11.1=hcf80075_0
79
+ - libstdcxx=15.1.0=h8f9b012_3
80
+ - libstdcxx-ng=15.1.0=h4852527_3
81
+ - libtorch=2.3.1=cuda118_h7aef8b2_300
82
+ - liburing=2.7=h434a139_0
83
+ - libuuid=2.38.1=h0b41bf4_0
84
+ - libuv=1.51.0=hb9d3cd8_0
85
+ - libxcrypt=4.4.36=hd590300_1
86
+ - libxml2=2.13.8=h4bc477f_0
87
+ - libzlib=1.3.1=hb9d3cd8_2
88
+ - llvm-openmp=20.1.8=h4922eb0_0
89
+ - markdown=3.8.2=pyhd8ed1ab_0
90
+ - markdown-it-py=3.0.0=pyhd8ed1ab_1
91
+ - markupsafe=3.0.2=py310h89163eb_1
92
+ - mdurl=0.1.2=pyhd8ed1ab_1
93
+ - metis=5.1.1=h59595ed_2
94
+ - mkl=2023.2.0=h84fe81f_50496
95
+ - ml_dtypes=0.4.0=py310h5eaa309_2
96
+ - mpc=1.3.1=h24ddda3_1
97
+ - mpfr=4.2.1=h90cbb55_3
98
+ - mpmath=1.3.0=pyhd8ed1ab_1
99
+ - namex=0.1.0=pyhd8ed1ab_0
100
+ - nccl=2.27.3.1=h03a54cd_0
101
+ - ncurses=6.5=h2d0b736_3
102
+ - networkx=3.4.2=pyh267e887_2
103
+ - numpy=1.26.4=py310hb13e2d6_0
104
+ - openssl=3.5.1=h7b32b05_0
105
+ - opt_einsum=3.4.0=pyhd8ed1ab_1
106
+ - optree=0.16.0=py310h3788b33_0
107
+ - packaging=25.0=pyh29332c3_1
108
+ - pandas=2.3.1=py310h0158d43_0
109
+ - pip=25.1.1=pyh8b19718_0
110
+ - protobuf=4.25.3=py310h0e2eeba_1
111
+ - psutil=7.0.0=py310ha75aee5_0
112
+ - pycparser=2.22=pyh29332c3_1
113
+ - pydantic=2.11.7=pyh3cfb1c2_0
114
+ - pydantic-core=2.33.2=py310hbcd0ec0_0
115
+ - pygments=2.19.2=pyhd8ed1ab_0
116
+ - pysocks=1.7.1=pyha55dd90_7
117
+ - python=3.10.18=hd6af730_0_cpython
118
+ - python-dateutil=2.9.0.post0=pyhe01879c_2
119
+ - python-flatbuffers=25.2.10=pyhbc23db3_0
120
+ - python-tzdata=2025.2=pyhd8ed1ab_0
121
+ - python_abi=3.10=7_cp310
122
+ - pytorch=2.3.1=cuda118_py310he8d5cbe_300
123
+ - pytz=2025.2=pyhd8ed1ab_0
124
+ - pyyaml=6.0.2=py310h89163eb_2
125
+ - re2=2023.09.01=h7f4b329_2
126
+ - readline=8.2=h8c095d6_2
127
+ - requests=2.32.4=pyhd8ed1ab_0
128
+ - rich=14.0.0=pyh29332c3_0
129
+ - scipy=1.15.2=py310h1d65ade_0
130
+ - setuptools=80.9.0=pyhff2d567_0
131
+ - six=1.17.0=pyhd8ed1ab_0
132
+ - sleef=3.8=h1b44611_0
133
+ - snappy=1.2.1=h8bd8927_1
134
+ - sympy=1.14.0=pyh2585a3b_105
135
+ - sysroot_linux-64=2.28=h4ee821c_8
136
+ - tbb=2021.13.0=hceb3a55_1
137
+ - tensorboard=2.17.1=pyhd8ed1ab_0
138
+ - tensorboard-data-server=0.7.0=py310h6c63255_2
139
+ - tensorflow=2.17.0=cpu_py310h42475c5_2
140
+ - tensorflow-base=2.17.0=cpu_py310h98e3cc3_2
141
+ - tensorflow-estimator=2.17.0=cpu_py310heba74a3_2
142
+ - termcolor=3.1.0=pyhd8ed1ab_0
143
+ - tk=8.6.13=noxft_hd72426e_102
144
+ - tqdm=4.67.1=pyhd8ed1ab_1
145
+ - typing-extensions=4.14.1=h4440ef1_0
146
+ - typing-inspection=0.4.1=pyhd8ed1ab_0
147
+ - typing_extensions=4.14.1=pyhe01879c_0
148
+ - tzdata=2025b=h78e105d_0
149
+ - urllib3=2.5.0=pyhd8ed1ab_0
150
+ - werkzeug=3.1.3=pyhd8ed1ab_1
151
+ - wheel=0.45.1=pyhd8ed1ab_1
152
+ - wrapt=1.17.2=py310ha75aee5_0
153
+ - yaml=0.2.5=h7f98852_2
154
+ - zipp=3.23.0=pyhd8ed1ab_0
155
+ - zstandard=0.23.0=py310ha75aee5_2
156
+ - zstd=1.5.7=hb8e6e7a_2
157
+ - pip:
158
+ - anyio==4.9.0
159
+ - argon2-cffi==25.1.0
160
+ - argon2-cffi-bindings==21.2.0
161
+ - arrow==1.3.0
162
+ - asttokens==3.0.0
163
+ - async-lru==2.0.5
164
+ - attrs==25.3.0
165
+ - awkward==2.8.5
166
+ - awkward-cpp==47
167
+ - babel==2.17.0
168
+ - beautifulsoup4==4.13.4
169
+ - bleach==6.2.0
170
+ - comm==0.2.2
171
+ - contourpy==1.3.2
172
+ - cramjam==2.10.0
173
+ - cycler==0.12.1
174
+ - debugpy==1.8.15
175
+ - decorator==5.2.1
176
+ - defusedxml==0.7.1
177
+ - exceptiongroup==1.3.0
178
+ - executing==2.2.0
179
+ - fastjsonschema==2.21.1
180
+ - fonttools==4.59.0
181
+ - fqdn==1.5.1
182
+ - h11==0.16.0
183
+ - httpcore==1.0.9
184
+ - httpx==0.28.1
185
+ - ipykernel==6.29.5
186
+ - ipython==8.37.0
187
+ - isoduration==20.11.0
188
+ - jedi==0.19.2
189
+ - joblib==1.5.1
190
+ - json5==0.12.0
191
+ - jsonpointer==3.0.0
192
+ - jsonschema==4.24.0
193
+ - jsonschema-specifications==2025.4.1
194
+ - jupyter-client==8.6.3
195
+ - jupyter-core==5.8.1
196
+ - jupyter-events==0.12.0
197
+ - jupyter-lsp==2.2.5
198
+ - jupyter-server==2.16.0
199
+ - jupyter-server-terminals==0.5.3
200
+ - jupyterlab==4.4.4
201
+ - jupyterlab-pygments==0.3.0
202
+ - jupyterlab-server==2.27.3
203
+ - kiwisolver==1.4.8
204
+ - matplotlib==3.10.3
205
+ - matplotlib-inline==0.1.7
206
+ - mistune==3.1.3
207
+ - nbclient==0.10.2
208
+ - nbconvert==7.16.6
209
+ - nbformat==5.10.4
210
+ - nest-asyncio==1.6.0
211
+ - notebook-shim==0.2.4
212
+ - overrides==7.7.0
213
+ - pandocfilters==1.5.1
214
+ - parso==0.8.4
215
+ - pexpect==4.9.0
216
+ - pillow==11.3.0
217
+ - platformdirs==4.3.8
218
+ - prometheus-client==0.22.1
219
+ - prompt-toolkit==3.0.51
220
+ - ptyprocess==0.7.0
221
+ - pure-eval==0.2.3
222
+ - pyparsing==3.2.3
223
+ - python-json-logger==3.3.0
224
+ - pyzmq==27.0.0
225
+ - referencing==0.36.2
226
+ - rfc3339-validator==0.1.4
227
+ - rfc3986-validator==0.1.1
228
+ - rpds-py==0.26.0
229
+ - scikit-learn==1.7.0
230
+ - send2trash==1.8.3
231
+ - sniffio==1.3.1
232
+ - soupsieve==2.7
233
+ - stack-data==0.6.3
234
+ - terminado==0.18.1
235
+ - threadpoolctl==3.6.0
236
+ - tinycss2==1.4.0
237
+ - tomli==2.2.1
238
+ - torchdata==0.9.0
239
+ - tornado==6.5.1
240
+ - traitlets==5.14.3
241
+ - types-python-dateutil==2.9.0.20250708
242
+ - uproot==5.6.3
243
+ - uri-template==1.3.0
244
+ - wcwidth==0.2.13
245
+ - webcolors==24.11.1
246
+ - webencodings==0.5.1
247
+ - websocket-client==1.8.0
248
+ - xxhash==3.5.0
249
+ prefix: /global/homes/c/chult/.conda/envs/pytorch_dgl_cf
root_gnn_dgl/setup/launch_image.sh DELETED
@@ -1,9 +0,0 @@
1
- podman-hpc run \
2
- -it \
3
- --mount type=bind,source=/pscratch/sd/j/joshuaho/,target=/pscratch/sd/j/joshuaho/ \
4
- --mount type=bind,source=/global/cfs/projectdirs/atlas/joshua/,target=/global/cfs/projectdirs/atlas/joshua/ \
5
- --rm \
6
- --network host \
7
- --gpu \
8
- --shm-size=32g \
9
- joshuaho/pytorch:1.0
 
 
 
 
 
 
 
 
 
 
training_time.png DELETED

Git LFS Details

  • SHA256: eccc855e8c797c433903e13422bd3e6024270e9db25decd8cba1d2233fd4166a
  • Pointer size: 131 Bytes
  • Size of remote file: 293 kB