Skip to content

Commit 886cf00

Browse files
committed
initial code commit
1 parent 4714aca commit 886cf00

File tree

8 files changed

+877
-0
lines changed

8 files changed

+877
-0
lines changed

run_dir/extargs.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/env python3
2+
logfile = "/path/to/logfile.txt"
3+
tr_dat_path = "/path/to/data.npy"
4+
tr_lab_path = "/path/to/labels.npy"
5+
nconstit = 50
6+
model_dim = 1000
7+
output_dim = 1000
8+
n_heads = 4
9+
dim_feedforward = 1000
10+
n_layers = 4
11+
n_head_layers = 2
12+
opt = "adam"
13+
sbratio = 1.0
14+
n_epochs = 500
15+
learning_rate = 0.00005
16+
batch_size = 128
17+
temperature = 0.10
18+
rot = True
19+
ptd = True
20+
ptcm = 0.1
21+
ptst = 0.1
22+
trs = True
23+
trsw = 1.0
24+
cf = True
25+
mask= False
26+
cmask = True
27+
expt = "experiment-name"
28+

scripts/modules/fcn.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
import sys
3+
import numpy as np
4+
import random
5+
import time
6+
7+
import matplotlib.pyplot as plt
8+
import torch
9+
import torch.nn as nn
10+
import torch.nn.functional as F
11+
12+
# class for fully connected neural network
13+
class fully_connected_network( nn.Module ):
14+
# define and intialize the structure of the neural network
15+
def __init__( self, input_size, output_size, hidden_size, n_hidden, dropout_rate, opt, learning_rate ):
16+
super( fully_connected_network, self ).__init__()
17+
# define hyperparameters
18+
self.input_size = input_size
19+
self.output_size = output_size
20+
self.hidden_size = hidden_size
21+
self.n_hidden = n_hidden
22+
self.opt = opt
23+
self.learning_rate = learning_rate
24+
self.dropout_rate = dropout_rate
25+
# define layers
26+
self.input_layer = nn.Linear( self.input_size, self.hidden_size )
27+
self.hidden_layers = nn.ModuleList()
28+
self.dropout = nn.Dropout( p=self.dropout_rate )
29+
for i in range( self.n_hidden ):
30+
self.hidden_layers.append( nn.Linear( self.hidden_size, self.hidden_size ) )
31+
self.output_layer = nn.Linear( self.hidden_size, self.output_size )
32+
if self.opt == "adam":
33+
self.optimizer = torch.optim.Adam( self.parameters(), lr=self.learning_rate )
34+
if self.opt == "sgd":
35+
self.optimizer = torch.optim.SGD( self.parameters(), lr=self.learning_rate )
36+
37+
def forward( self, x ):
38+
x = F.relu( self.input_layer( x ) )
39+
for layer in self.hidden_layers:
40+
x = F.relu(layer( x ))
41+
x = self.dropout( x )
42+
output = self.output_layer( x )
43+
return output

scripts/modules/fcn_linear.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import os
2+
import sys
3+
import numpy as np
4+
import random
5+
import time
6+
7+
import matplotlib.pyplot as plt
8+
import torch
9+
import torch.nn as nn
10+
import torch.nn.functional as F
11+
12+
# class for fully connected linear neural network
13+
class fully_connected_linear_network( nn.Module ):
14+
# define and intialize the structure of the neural network
15+
def __init__( self, input_size, output_size, opt, learning_rate ):
16+
super( fully_connected_linear_network, self ).__init__()
17+
# define hyperparameters
18+
self.input_size = input_size
19+
self.output_size = output_size
20+
self.opt = opt
21+
self.learning_rate = learning_rate
22+
# define layers
23+
self.layer = nn.Linear( self.input_size, self.output_size )
24+
if self.opt == "adam":
25+
self.optimizer = torch.optim.Adam( self.parameters(), lr=self.learning_rate )
26+
if self.opt == "sgd":
27+
self.optimizer = torch.optim.SGD( self.parameters(), lr=self.learning_rate )
28+
def forward( self, x ):
29+
output = self.layer( x )
30+
return output

scripts/modules/jet_augs.py

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
import os
2+
import sys
3+
import numpy as np
4+
import random
5+
import time
6+
7+
import matplotlib.pyplot as plt
8+
import torch
9+
import torch.nn as nn
10+
import torch.nn.functional as F
11+
12+
13+
def translate_jets( batch, width=1.0 ):
14+
'''
15+
Input: batch of jets, shape (batchsize, 3, n_constit)
16+
dim 1 ordering: (pT, eta, phi)
17+
Output: batch of eta-phi translated jets, same shape as input
18+
'''
19+
mask = (batch[:,0] > 0) # 1 for constituents with non-zero pT, 0 otherwise
20+
ptp_eta = np.ptp(batch[:,1,:], axis=-1, keepdims=True) # ptp = 'peak to peak' = max - min
21+
ptp_phi = np.ptp(batch[:,2,:], axis=-1, keepdims=True) # ptp = 'peak to peak' = max - min
22+
low_eta = -width*ptp_eta
23+
high_eta = +width*ptp_eta
24+
low_phi = np.maximum(-width*ptp_phi, -np.pi-np.amin(batch[:,2,:], axis=1).reshape(ptp_phi.shape))
25+
high_phi = np.minimum(+width*ptp_phi, +np.pi-np.amax(batch[:,2,:], axis=1).reshape(ptp_phi.shape))
26+
shift_eta = mask*np.random.uniform(low=low_eta, high=high_eta, size=(batch.shape[0], 1))
27+
shift_phi = mask*np.random.uniform(low=low_phi, high=high_phi, size=(batch.shape[0], 1))
28+
shift = np.stack([np.zeros((batch.shape[0], batch.shape[2])), shift_eta, shift_phi], 1)
29+
shifted_batch = batch+shift
30+
return shifted_batch
31+
32+
33+
def rotate_jets( batch ):
34+
'''
35+
Input: batch of jets, shape (batchsize, 3, n_constit)
36+
dim 1 ordering: (pT, eta, phi)
37+
Output: batch of jets rotated independently in eta-phi, same shape as input
38+
'''
39+
rot_angle = np.random.rand(batch.shape[0])*2*np.pi
40+
c = np.cos(rot_angle)
41+
s = np.sin(rot_angle)
42+
o = np.ones_like(rot_angle)
43+
z = np.zeros_like(rot_angle)
44+
rot_matrix = np.array([[o, z, z], [z, c, -s], [z, s, c]]) # (3, 3, batchsize)
45+
return np.einsum('ijk,lji->ilk', batch, rot_matrix)
46+
47+
def normalise_pts( batch ):
48+
'''
49+
Input: batch of jets, shape (batchsize, 3, n_constit)
50+
dim 1 ordering: (pT, eta, phi)
51+
Output: batch of pT-normalised jets, pT in each jet sums to 1, same shape as input
52+
'''
53+
batch_norm = batch.copy()
54+
batch_norm[:,0,:] = np.nan_to_num(batch_norm[:,0,:]/np.sum(batch_norm[:,0,:], axis=1)[:, np.newaxis], posinf = 0.0, neginf = 0.0 )
55+
return batch_norm
56+
57+
def rescale_pts( batch ):
58+
'''
59+
Input: batch of jets, shape (batchsize, 3, n_constit)
60+
dim 1 ordering: (pT, eta, phi)
61+
Output: batch of pT-rescaled jets, each constituent pT is rescaled by 600, same shape as input
62+
'''
63+
batch_rscl = batch.copy()
64+
batch_rscl[:,0,:] = np.nan_to_num(batch_rscl[:,0,:]/600, posinf = 0.0, neginf = 0.0 )
65+
return batch_rscl
66+
67+
def crop_jets( batch, nc ):
68+
'''
69+
Input: batch of jets, shape (batchsize, 3, n_constit)
70+
dim 1 ordering: (pT, eta, phi)
71+
Output: batch of cropped jets, each jet is cropped to nc constituents, shape (batchsize, 3, nc)
72+
'''
73+
batch_crop = batch.copy()
74+
return batch_crop[:,:,0:nc]
75+
76+
def distort_jets( batch, strength=0.1, pT_clip_min=0.1 ):
77+
'''
78+
Input: batch of jets, shape (batchsize, 3, n_constit)
79+
dim 1 ordering: (pT, eta, phi)
80+
Output: batch of jets with each constituents position shifted independently, shifts drawn from normal with mean 0, std strength/pT, same shape as input
81+
'''
82+
pT = batch[:,0] # (batchsize, n_constit)
83+
shift_eta = np.nan_to_num( strength * np.random.randn(batch.shape[0], batch.shape[2]) / pT.clip(min=pT_clip_min), posinf = 0.0, neginf = 0.0 )# * mask
84+
shift_phi = np.nan_to_num( strength * np.random.randn(batch.shape[0], batch.shape[2]) / pT.clip(min=pT_clip_min), posinf = 0.0, neginf = 0.0 )# * mask
85+
shift = np.stack( [ np.zeros( (batch.shape[0], batch.shape[2]) ), shift_eta, shift_phi ], 1)
86+
return batch + shift
87+
88+
def collinear_fill_jets( batch ):
89+
'''
90+
Input: batch of jets, shape (batchsize, 3, n_constit)
91+
dim 1 ordering: (pT, eta, phi)
92+
Output: batch of jets with collinear splittings, the function attempts to fill as many of the zero-padded args.nconstit
93+
entries with collinear splittings of the constituents by splitting each constituent at most once, same shape as input
94+
'''
95+
batchb = batch.copy()
96+
nc = batch.shape[2]
97+
nzs = np.array( [ np.where( batch[:,0,:][i]>0.0)[0].shape[0] for i in range(len(batch)) ] )
98+
for k in range(len(batch)):
99+
nzs1 = np.max( [ nzs[k], int(nc/2) ] )
100+
zs1 = int(nc-nzs1)
101+
els = np.random.choice( np.linspace(0,nzs1-1,nzs1), size=zs1, replace=False )
102+
rs = np.random.uniform( size=zs1 )
103+
for j in range(zs1):
104+
batchb[k,0,int(els[j])] = rs[j]*batch[k,0,int(els[j])]
105+
batchb[k,0,int(nzs[k]+j)] = (1-rs[j])*batch[k,0,int(els[j])]
106+
batchb[k,1,int(nzs[k]+j)] = batch[k,1,int(els[j])]
107+
batchb[k,2,int(nzs[k]+j)] = batch[k,2,int(els[j])]
108+
return batchb

scripts/modules/losses.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
import sys
3+
import numpy as np
4+
import matplotlib.pyplot as plt
5+
6+
import torch
7+
import torch.nn as nn
8+
import torch.nn.functional as F
9+
10+
def contrastive_loss( x_i, x_j, temperature ):
11+
xdevice = x_i.get_device()
12+
batch_size = x_i.shape[0]
13+
z_i = F.normalize( x_i, dim=1 )
14+
z_j = F.normalize( x_j, dim=1 )
15+
z = torch.cat( [z_i, z_j], dim=0 )
16+
similarity_matrix = F.cosine_similarity( z.unsqueeze(1), z.unsqueeze(0), dim=2 )
17+
sim_ij = torch.diag( similarity_matrix, batch_size )
18+
sim_ji = torch.diag( similarity_matrix, -batch_size )
19+
positives = torch.cat( [sim_ij, sim_ji], dim=0 )
20+
nominator = torch.exp( positives / temperature )
21+
negatives_mask = ( ~torch.eye( 2*batch_size, 2*batch_size, dtype=bool ) ).float()
22+
negatives_mask = negatives_mask.to( xdevice )
23+
denominator = negatives_mask * torch.exp( similarity_matrix / temperature )
24+
loss_partial = -torch.log( nominator / torch.sum( denominator, dim=1 ) )
25+
loss = torch.sum( loss_partial )/( 2*batch_size )
26+
return loss
27+
28+
def align_loss(x, y, alpha=2):
29+
xdevice = x.get_device()
30+
reps_x = x.clone()
31+
reps_y = y.clone()
32+
reps_x = F.normalize(reps_x, dim=1).to(xdevice)
33+
reps_y = F.normalize(reps_y, dim=1).to(xdevice)
34+
loss_align = (reps_x-reps_y).norm(p=2, dim=1).pow(exponent=alpha).mean()
35+
return loss_align
36+
37+
def uniform_loss(x, t=2):
38+
xdevice = x.get_device()
39+
reps_x = x.clone()
40+
reps_x = F.normalize(reps_x, dim=1).to(xdevice)
41+
loss_uniform = torch.pdist(reps_x, p=2).pow(2).mul(-t).exp().mean().log()
42+
return loss_uniform
43+

scripts/modules/perf_eval.py

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# import standard python modules
2+
import os
3+
import sys
4+
import numpy as np
5+
from sklearn import metrics
6+
7+
# import torch modules
8+
import torch
9+
import torch.nn as nn
10+
import torch.nn.functional as F
11+
12+
# import simple FCN network
13+
from modules.fcn_linear import fully_connected_linear_network
14+
from modules.fcn import fully_connected_network
15+
16+
# import preprocessing functions
17+
from sklearn.preprocessing import StandardScaler, MaxAbsScaler, RobustScaler
18+
19+
def find_nearest( array, value ):
20+
array = np.asarray( array )
21+
idx = ( np.abs( array-value ) ).argmin()
22+
return array[idx]
23+
24+
def get_perf_stats( labels, measures ):
25+
measures = np.nan_to_num( measures )
26+
auc = metrics.roc_auc_score( labels, measures )
27+
fpr,tpr,thresholds = metrics.roc_curve( labels, measures )
28+
fpr2 = [ fpr[i] for i in range( len( fpr ) ) if tpr[i]>=0.5]
29+
tpr2 = [ tpr[i] for i in range( len( tpr ) ) if tpr[i]>=0.5]
30+
try:
31+
imtafe = np.nan_to_num( 1 / fpr2[ list( tpr2 ).index( find_nearest( list( tpr2 ), 0.5 ) ) ] )
32+
except:
33+
imtafe = 1
34+
return auc, imtafe
35+
36+
def linear_classifier_test( linear_input_size, linear_batch_size, linear_n_epochs, linear_opt, linear_learning_rate, reps_tr_in, trlab_in, reps_te_in, telab_in ):
37+
xdevice = torch.device( "cuda" if torch.cuda.is_available() else "cpu" )
38+
fcn_linear = fully_connected_linear_network( linear_input_size, 1, linear_opt, linear_learning_rate )
39+
fcn_linear.to( xdevice )
40+
bce_loss = nn.BCELoss()
41+
sigmoid = nn.Sigmoid()
42+
losses = []
43+
if linear_opt == "sgd":
44+
scheduler = torch.optim.lr_scheduler.StepLR( fcn_linear.optimizer, 100, gamma=0.6, last_epoch=-1, verbose=False)
45+
for epoch in range( linear_n_epochs ):
46+
indices_list = torch.split( torch.randperm( reps_tr_in.shape[0] ), linear_batch_size )
47+
losses_e = []
48+
for i, indices in enumerate( indices_list ):
49+
fcn_linear.optimizer.zero_grad()
50+
x = reps_tr_in[indices,:]
51+
l = trlab_in[indices]
52+
x = torch.Tensor( x ).view( -1, linear_input_size ).to( xdevice )
53+
l = torch.Tensor( l ).view( -1, 1 ).to( xdevice )
54+
z = sigmoid( fcn_linear( x ) ).to( xdevice )
55+
loss = bce_loss( z, l ).to( xdevice )
56+
loss.backward()
57+
fcn_linear.optimizer.step()
58+
losses_e.append( loss.detach().cpu().numpy() )
59+
losses.append( np.mean( np.array( losses_e ) ) )
60+
if linear_opt == "sgd":
61+
scheduler.step()
62+
out_dat = fcn_linear( torch.Tensor( reps_te_in ).view(-1, linear_input_size).to( xdevice ) ).detach().cpu().numpy()
63+
out_lbs = telab_in
64+
return out_dat, out_lbs, losses
65+

0 commit comments

Comments
 (0)