-
Notifications
You must be signed in to change notification settings - Fork 3
Beamline neural network reconstruction training #171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
101 commits
Select commit
Hold shift + click to select a range
08586ff
Added files
simonge df1b38e
Update
simonge 810cc3b
Make canvas name more useful
simonge 0973e5d
Add beam generator macro
simonge 1323fe0
Update analysis
simonge 6329372
Add phasespace scripts
simonge 67d765c
Change name of functors
simonge 3afabcb
Remove image and acceptance benchmarks for now
simonge 99633c2
Prepare for CI testing
simonge 0deb701
Remove other benchmarks
simonge 163341b
Add missing config.yml
simonge 7a58355
Correct typo
simonge 5cd62be
Re-enable other benchmarks and update cores
simonge 312ca42
Add some pass fail checks
simonge 02e0c0e
Set sim and analysis dir by variable
simonge e39d0f9
Revert exclusion of other benchmarks
simonge 67d4206
Review suggestions
simonge 81fad99
Snakefile: fix for out-of-tree running
veprbl 6b21ff1
Snakefile restore indentation
veprbl b18bf3f
Add header to inputs too
simonge c7e268f
Add low-q2 phase space electron tests
simonge c964d40
Add acceptance sim
simonge 8b98ed6
Make simulation run with correct range and 1000x faster
simonge 31fe8ef
Add outputs from script
simonge ccddf53
Change code inputs to workflow source path
simonge f44d690
rename phasespace to acceptance
simonge 4df2119
Remove unused code
simonge 96e8b50
Define both simulations in the yml
simonge 40d4fe8
Merge remote-tracking branch 'origin/master' into beamline_acceptance
simonge 6878af8
Add entry fraction plot
simonge 09f8681
Make filtering more robust
simonge 40e1fa9
Change entry limit warning
simonge 158c8ef
Add reconstruction training based on beampipe exit
simonge d937fdb
Update model and atempt to setup snakemake
simonge e5a4ab8
Fix snakemane rule and silence npsim info
simonge 13030cc
Fix snakemake attribute
simonge 02665c3
Scale momentum to unit vector
simonge 16adc7f
Add tensors to device too
simonge a208cd7
Update benchmarks/beamline/Snakefile
simonge d2ebe91
Various improvements
simonge c02b517
Merge branch 'beamline_training' of github.com:eic/detector_benchmark…
simonge 48b1e11
Merge remote-tracking branch 'origin/master' into beamline_training
simonge ae27686
Lots of updates, filtering of lowq2 hepmc events
simonge 3075944
Add some versitility
simonge ecd5829
Add resolution test
simonge 91b5041
Change phi plots to degrees
simonge 7723f89
Extra workflow steps and fixes
simonge 322768a
Swapping to huberloss helps
simonge 5613274
Merge remote-tracking branch 'origin/master' into beamline_training
simonge 0238978
Move reconstruction to separate benchmark
simonge 6a27a3e
include lowq2_reconstruction in snakefile
simonge fafb5e1
Rename processData to cleanData
simonge ec179b4
Rename ProcessData to LoadData
simonge 5dc2f28
Add lowq2_reconstruction snakefile
simonge 1fcba19
Update CI bits
simonge c0855b8
Temporarily comment out other benchmarks
simonge 999fb63
Fix namings maybe
simonge 2e50f83
Add failure conditions on resolutions
simonge e44eac7
Fix benchmark stage
simonge 1fddc48
Fix naming
simonge 7e38cdc
Allow int return to flag fail
simonge 673af74
Separate resolution check from plot creation
simonge 9dbd3aa
Fix naming and add onnx
simonge b6cde3b
Merge remote-tracking branch 'origin/master' into beamline_training
simonge 7606250
Merge updates from training-CI branch
simonge 06ba1dc
Fix beamline running
simonge f4f68e9
Require successful beamline benchmark before triggering reconstructio…
simonge 0a89651
Remove optional projection from old inputs
simonge 0f8f68d
Reinclude beamline benchmarks
simonge 349cc53
Re-enable in snakefile too
simonge bce7cff
Merge branch 'master' into beamline_training
simonge 8fbf0a0
Merge branch 'master' into beamline_training
simonge 8d30eab
Update default
simonge 425b16e
Merge branch 'beamline_training' of github.com:eic/detector_benchmark…
simonge 9da9148
Fix spelling which found its way back in
simonge ede83e7
Try adding Caching
simonge c585013
Fix eicrecon options
veprbl 9809b89
Temporary break reconstruction limits
simonge f82c8ad
Test python requirements
simonge e0093eb
remove argparse from requirements
simonge a6356ca
Add onnx dependancies
simonge 04f08eb
Reduce events and epochs for testing
simonge 5379d25
Use static opset version
simonge 237eff3
add missing comma
simonge 5488f48
Try some static versions
simonge 8fa74ee
Update requirements to match eic shell
simonge b3bceea
Don't require gpu torch
simonge 41af472
Try again
simonge 8ab7b44
Test new workflow with added checks
simonge b719382
Try with other spelling
simonge a586f09
Try multiline formatting
simonge 3f3e632
Remove explicit artifact declatation
simonge 5e21f71
Remove other overwriting artifact declaration....
simonge 7442174
Revert "Reduce events and epochs for testing"
simonge bfffb83
rename retraining jobs
simonge cf1825e
Revert "Temporary break reconstruction limits"
simonge 1d2abf3
Split collect results
simonge e4cda34
Fix requirement name
simonge 208dc20
reenable other benchmarks
simonge 373588a
Update names of plots to include Low-Q2
simonge abca061
Add electron_beamline prefix to beamline outputs
simonge File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import uproot | ||
| import awkward as ak | ||
|
|
||
| def create_arrays(dataFiles,featureName="_TaggerTrackerFeatureTensor_floatData",targetName="_TaggerTrackerTargetTensor_floatData", entries=None, treeName="events"): | ||
|
|
||
| # List of branches to load | ||
| branches = [featureName,targetName] | ||
|
|
||
| # Load data from concatenated list of files | ||
| data = uproot.concatenate([f"{file}:{treeName}" for file in dataFiles], branches, entry_stop=entries, library="ak") | ||
|
|
||
| input_data = data[featureName] | ||
| target_data = data[targetName] | ||
|
|
||
| return input_data, target_data |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| import torch | ||
| import torch.nn as nn | ||
| import torch.optim as optim | ||
| import numpy as np | ||
|
|
||
| class ProjectToX0Plane(nn.Module): | ||
| def forward(self, x): | ||
| # x shape: (batch, 6) -> [x, y, z, px, py, pz] | ||
| x0, y0, z0, px, py, pz = x.unbind(dim=1) | ||
|
|
||
| # Normalize momentum components | ||
| momentum = torch.sqrt(px**2 + py**2 + pz**2) | ||
| px_norm = px / momentum | ||
| py_norm = py / momentum | ||
| pz_norm = pz / momentum | ||
|
|
||
| # Avoid division by zero for px | ||
| # eps = 1e-8 | ||
| # px_safe = torch.where(px_norm.abs() < eps, eps * torch.sign(px_norm) + eps, px_norm) | ||
| t = -x0 / px_norm | ||
|
|
||
| y_proj = y0 + py_norm * t | ||
| z_proj = z0 + pz_norm * t | ||
|
|
||
| # Output: [y_proj, z_proj, px_norm, py_norm] | ||
| return torch.stack([y_proj, z_proj, px_norm, py_norm], dim=1) | ||
|
|
||
| def project_numpy(self, arr): | ||
| """ | ||
| Projects a numpy array of shape (N, 6) using the forward method, | ||
| returns a numpy array of shape (N, 4). | ||
| """ | ||
| device = next(self.parameters()).device if any(p.device.type != 'cpu' for p in self.parameters()) else 'cpu' | ||
| x = torch.from_numpy(arr).float().to(device) | ||
| with torch.no_grad(): | ||
| projected = self.forward(x) | ||
| return projected.cpu().numpy() | ||
|
|
||
| class RegressionModel(nn.Module): | ||
| def __init__(self): | ||
| super(RegressionModel, self).__init__() | ||
| self.project_to_x0 = ProjectToX0Plane() | ||
| self.fc1 = nn.Linear(4, 512) | ||
| self.fc2 = nn.Linear(512, 64) | ||
| self.fc3 = nn.Linear(64, 3) # Output layer for | ||
|
|
||
| # Normalization parameters | ||
| self.input_mean = nn.Parameter(torch.zeros(4), requires_grad=False) | ||
| self.input_std = nn.Parameter(torch.ones(4), requires_grad=False) | ||
| self.output_mean = nn.Parameter(torch.zeros(3), requires_grad=False) | ||
| self.output_std = nn.Parameter(torch.ones(3), requires_grad=False) | ||
|
|
||
|
|
||
| def forward(self, x): | ||
| # Conditionally apply projection | ||
| x = self.project_to_x0(x) | ||
| # Normalize inputs | ||
| x = (x - self.input_mean) / self.input_std | ||
|
|
||
| # Pass through the fully connected layers | ||
| x = self._core_forward(x) | ||
|
|
||
| # Denormalize outputs | ||
| x = x * self.output_std + self.output_mean | ||
| return x | ||
|
|
||
| def _core_forward(self, x): | ||
| # Core fully connected layers | ||
| x = torch.relu(self.fc1(x)) | ||
| x = torch.relu(self.fc2(x)) | ||
| x = self.fc3(x) | ||
| return x | ||
|
|
||
| def adapt(self, input_data, output_data): | ||
| # Normalization | ||
| self.input_mean.data = input_data.mean(dim=0) | ||
| self.input_std.data = input_data.std(dim=0) | ||
| self.output_mean.data = output_data.mean(dim=0) | ||
| self.output_std.data = output_data.std(dim=0) | ||
|
|
||
| def preprocess_data(model, data_loader, adapt=True): | ||
| inputs = data_loader.dataset.tensors[0] | ||
| targets = data_loader.dataset.tensors[1] | ||
|
|
||
|
|
||
| projected_inputs = model.project_to_x0(inputs) | ||
|
|
||
| # Compute normalization parameters | ||
| if adapt: | ||
| model.adapt(projected_inputs, targets) | ||
|
|
||
| # Normalize inputs and targets | ||
| normalized_inputs = (projected_inputs - model.input_mean ) / model.input_std | ||
| normalized_targets = (targets - model.output_mean) / model.output_std | ||
|
|
||
| # Replace the dataset with preprocessed data | ||
| data_loader.dataset.tensors = (normalized_inputs, normalized_targets) | ||
|
|
||
| def makeModel(): | ||
| # Create the model | ||
| model = RegressionModel() | ||
| # Define the optimizer | ||
| optimizer = optim.Adam(model.parameters(), lr=0.0004) | ||
| # Define the loss function | ||
| criterion = nn.HuberLoss(delta=0.2) # Huber loss for regression tasks | ||
|
|
||
| return model, optimizer, criterion | ||
|
|
||
| def trainModel(epochs, train_loader, val_loader, device): | ||
|
|
||
| model, optimizer, criterion = makeModel() | ||
|
|
||
| model.to(device) | ||
|
|
||
| # Preprocess training and validation data | ||
| preprocess_data(model, train_loader, adapt=True) | ||
|
|
||
| # Preprocess validation data without adapting | ||
| preprocess_data(model, val_loader, adapt=False) | ||
|
|
||
| # Move data to the GPU | ||
| train_loader.dataset.tensors = (train_loader.dataset.tensors[0].to(device), train_loader.dataset.tensors[1].to(device)) | ||
| val_loader.dataset.tensors = (val_loader.dataset.tensors[0].to(device), val_loader.dataset.tensors[1].to(device)) | ||
|
|
||
| # Verify that the model parameters are on the GPU | ||
| for name, param in model.named_parameters(): | ||
| print(f"{name} is on {param.device}") | ||
|
|
||
| for epoch in range(epochs): | ||
| model.train() | ||
| running_loss = 0.0 | ||
| for inputs, targets in train_loader: | ||
| optimizer.zero_grad() | ||
| outputs = model._core_forward(inputs) | ||
| loss = criterion(outputs, targets) | ||
| loss.backward() | ||
| optimizer.step() | ||
| running_loss += loss.item() * inputs.size(0) | ||
|
|
||
| epoch_loss = running_loss / len(train_loader.dataset) | ||
|
|
||
|
|
||
| # Validation step | ||
| model.eval() | ||
| val_loss = 0.0 | ||
| with torch.no_grad(): | ||
| for val_inputs, val_targets in val_loader: | ||
| val_outputs = model._core_forward(val_inputs) | ||
| val_loss += criterion(val_outputs, val_targets).item() * val_inputs.size(0) | ||
|
|
||
| val_loss /= len(val_loader.dataset) | ||
|
|
||
| print(f"Epoch [{epoch+1}/{epochs}], Loss: {epoch_loss}, Val Loss: {val_loss}") | ||
|
|
||
| return model |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.