n3fit.layers package

Submodules

n3fit.layers.DIS module

DIS layer

This layer produces a DIS observable, which can consists of one or more fktables. The rationale behind this layer is to keep all required operation in one single place such that is easier to optimize or modify.

Comment on the branching based on the number of replicas:

This is purely for performance, masking the PDF is more efficient than padding the fk table for one replica, and so is tensordot over einsum.

Some timings done on snellius using tensorflow 2.15.0 and varying these 2 factors:
CPUGPU | einsum | tensordot |
– | – | – |
mask pdf | - | 92 65 |

|mask fk | 330 53 | 177 53 |

These timings are all for one replica.

Crucially, einsum is a requirement of the multireplica case, while tensordot gives a benefit of a factor of 2x for the single replica case. Since this branching is required anyhow,

by masking the PDF for 1 replica instead of padding the fktable we get an extra factor of x2

class n3fit.layers.DIS.DIS(*args, **kwargs)[source]

Bases: Observable

The DIS class receives a list of active flavours and a fktable and prepares a layer that performs the convolution of said fktable with the incoming pdf.

The fktable is expected to be rank 3 (ndata, xgrid, flavours) while the input pdf is rank 4 of shape (batch_size, replicas, xgrid, flavours)

build(input_shape)[source]
gen_mask(basis)[source]

Receives a list of active flavours and generates a boolean mask tensor

Parameters:

basis (list(int)) – list of active flavours

Returns:

mask – rank 1 tensor (flavours)

Return type:

tensor

pad_fk(fk, mask)[source]

Combine an fk table and a mask into an fk table padded with zeroes for the inactive flavours, to be contracted with the full PDF.

Parameters:
  • fk (tensor) – FK table of shape (ndata, active_flavours, x)

  • mask (tensor) – mask of shape (flavours, active_flavours)

Returns:

padded_fk – masked fk table of shape ndata, x, flavours)

Return type:

tensor

n3fit.layers.DIS.compute_dis_observable_many_replica(pdf, padded_fk)[source]

Contract masked fk table with PDF.

Parameters:
  • pdf (list[tensor]) – list of pdf of shape (batch=1, replicas, xgrid, flavours)

  • padded_fk (tensor) – masked fk table of shape (ndata, xgrid, flavours)

Returns:

observable of shape (batch=1, replicas, ndata)

Return type:

tensor

n3fit.layers.DIS.compute_dis_observable_one_replica(pdf, padded_fk)[source]

Same operations as above but a specialized implementation that is more efficient for 1 replica, masking the PDF rather than the fk table.

n3fit.layers.DY module

class n3fit.layers.DY.DY(*args, **kwargs)[source]

Bases: Observable

Computes the convolution of two PDFs (the same one twice) and one fktable

build(input_shape)[source]
gen_mask(basis)[source]

Receives a list of active flavours and generates a boolean mask tensor

Parameters:

basis (list(int)) – list of active flavours

Returns:

mask – rank 2 tensor (flavours, flavours)

Return type:

tensor

pad_fk(fk, mask)[source]

Combine an fk table and a mask into an fk table padded with zeroes for the inactive flavours, to be contracted with the full PDF.

In the case of 1 replica, this is less efficient than masking the PDF directly, so we leave them separate.

Parameters:
  • fk (tensor) – FK table of shape (ndata, active_flavours, x, y)

  • mask (tensor) – mask of shape (flavours, flavours, active_flavours)

Returns:

  • padded_fk (tensor of shape ndata, x, flavours, y, flavours) (>1 replicas case))

  • (mask, fk) (tuple of inputs (1 replica case))

n3fit.layers.DY.compute_dy_observable_many_replica(pdf, padded_fk)[source]

Contract masked fk table with two PDFs.

Parameters:
  • pdf (list[tensor]) – list of pdf of shape (batch=1, replicas, xgrid, flavours)

  • padded_fk (tensor) – masked fk table of shape (ndata, xgrid, flavours, xgrid, flavours)

Returns:

observable of shape (batch=1, replicas, ndata)

Return type:

tensor

n3fit.layers.DY.compute_dy_observable_one_replica(pdf, mask_and_fk)[source]

Same operations as above but a specialized implementation that is more efficient for 1 replica, masking the PDF rather than the fk table.

n3fit.layers.losses module

Module containg the losses to be apply to the models as layers

The layer take the input from the model and acts on it producing a score function. For instance, in the case of the chi2 (LossInvcovmat) the function takes only the prediction of the model and, during instantiation, took the real data to compare with and the covmat.

class n3fit.layers.losses.LossIntegrability(*args, **kwargs)[source]

Bases: LossLagrange

Returns L = (y_pred)*(y_pred)

Example

>>> import numpy as np
>>> from n3fit.layers import losses
>>> pred = np.random.rand(1, 1, 5)
>>> loss_f = losses.LossIntegrability(c=1e2)
>>> loss_f(pred) > 0
True
apply_loss(y_pred)[source]
class n3fit.layers.losses.LossInvcovmat(*args, **kwargs)[source]

Bases: MetaLayer

Loss function such that: L = sum_{ij} (yt - yp)_{i} invcovmat_{ij} (yt - yp)_{j}

Takes as argument the inverse of the covmat and the target data. It also takes an optional argument to mask part of the predictions

Both the inverse covmat and the mask (if any) are stored as layer weights and can be updated at any points either directly or by using the update_mask and add_covmat methods.

Example

>>> import numpy as np
>>> from n3fit.layers import losses
>>> C = np.random.rand(5,5)
>>> data = np.random.rand(1, 1, 5)
>>> pred = np.random.rand(1, 1, 5)
>>> invC = np.linalg.inv( C @ C.T)
>>> loss_f = losses.LossInvcovmat(invC, data)
>>> loss_f(pred).shape == 1
True
add_covmat(covmat)[source]

Add a piece to the inverse covmat weights Note, however, that the _covmat attribute of the layer will still refer to the original data covmat

build(input_shape)[source]

Transform the inverse covmat and the mask into weights of the layers

call(y_pred, **kwargs)[source]
update_mask(new_mask)[source]

Update the mask

class n3fit.layers.losses.LossLagrange(*args, **kwargs)[source]

Bases: MetaLayer

Abstract loss function to apply lagrange multipliers to a model.

L = lambda * f(y)

The form of f(y) is given by modifying the apply_loss method. It is possible to modify how the multiplication of the lambda factor is implemented by modifying the apply_multiplier method.

The (non trainable) weight containing the multiplier is named lagMult.

apply_loss(y)[source]
apply_multiplier(y)[source]
build(input_shape)[source]
call(y_pred, **kwargs)[source]
class n3fit.layers.losses.LossPositivity(*args, **kwargs)[source]

Bases: LossLagrange

Returns L = lambda*elu(y_pred)

The positivity loss is computed by inverting the sign of the datapoints and then applying the elu function, this function is

f(x) = x if x > 0 f(x) = alpha * (e^{x} - 1) if x < 0

This is done to avoid a big discontinuity in the derivative at 0 when the lagrange multiplier is very big. In practice this function can produce results in the range (-alpha, inf)

Example

>>> import numpy as np
>>> from n3fit.layers import losses
>>> pred = np.random.rand(1, 1, 5)
>>> alpha = 1e-7
>>> c = 1e8
>>> loss_f = losses.LossPositivity(c=c, alpha=alpha)
>>> loss_f(pred) == -5*alpha
True
>>> loss_f(-pred) > c
True
apply_loss(y_pred)[source]

n3fit.layers.mask module

class n3fit.layers.mask.Mask(*args, **kwargs)[source]

Bases: MetaLayer

This layers applies a boolean mask to an input tensor. The mask admit a multiplier for all outputs which will be internally saved as a weight so it can be updated during trainig.

Typical usage is to apply training/validation split masks or applying a multiplier to a given layer

Parameters:
  • bool_mask (np.array of shape (n_replicas, n_features)) – numpy array with the boolean mask to be applied

  • c (float) – constant multiplier for every output

build(input_shape)[source]
call(ret)[source]

Apply the mask to the input tensor, and multiply by the constant if present.

Parameters:

ret (Tensor of shape (batch_size, n_replicas, n_features))

Return type:

Tensor of shape (batch_size, n_replicas, n_features)

n3fit.layers.msr_normalization module

Definition of the imposition of the Momentum Sum Rule and Valence Sum Rules to in the PDF fit.

In the module level constants {MSR/VSR}_COMPONENTS the flavours affected by the MSR and VSR are defined. For the Valence Sum Rule instead VSR_DENOMINATOR defines the integral of which flavour are used to compute the normalization. Note that for a Nf=4 fit v35=v24=v. If the number of flavours were to be changed in the future, this would need to be updated accordingly.

class n3fit.layers.msr_normalization.MSR_Normalization(*args, **kwargs)[source]

Bases: MetaLayer

Computes the normalisation factors for the sum rules of the PDFs.

Parameters:
  • mode (str) – The type of sum rule to apply, it can be one of ALL, MSR, VSR, TSR, ALLBUTCSR.

  • replica_seeds (List[int]) – A list of seed-per-replica. Used to sample the polarized sum rules.

call(pdf_integrated, photon_integral)[source]

Computes the normalization factors for the PDFs: A_g = (1-sigma-photon)/g A_v = A_v24 = A_v35 = 3/V A_v3 = 1/V_3 A_v8 = 3/V_8 A_v15 = 3/V_15

Note that both the input and the output are in the 14-flavours fk-basis

Parameters:
  • pdf_integrated ((Tensor(1, replicas, 14))) – the integrated PDF

  • photon_integral ((Tensor(1, replicas, 1))) – the integrated photon PDF

Returns:

normalization_factor – The normalization factors per flavour.

Return type:

Tensor(replicas, 1, 14)

n3fit.layers.msr_normalization.sample_tsr(sampler, component) list[source]

Sample the Triplets sum rules according to the PDG uncertainties.

Parameters:
  • sampler (np.random.Generator) – Numpy Generator from which to sample the TSR

  • c (str) – Component for which to sample from according to TSR_CONSTANTS

Returns:

value of the sum rule for this replica for this component sampled according to a normal distribution

Return type:

float

n3fit.layers.observable module

class n3fit.layers.observable.Observable(*args, **kwargs)[source]

Bases: MetaLayer, ABC

This class is the parent of the DIS and DY convolutions. All backend-dependent code necessary for the convolutions

is (must be) concentrated here

The methods gen_mask and call must be overriden by the observables where

  • gen_mask: it is called by the initializer and generates the mask between

    fktables and pdfs

  • call: this is what does the actual operation

Parameters:
  • fktable_data (list[validphys.coredata.FKTableData]) – list of FK which define basis and xgrid for the fktables in the list

  • fktable_arr (list) – list of fktables for this observable

  • operation_name (str) – string defining the name of the operation to be applied to the fktables

  • nfl (int) – number of flavours in the pdf (default:14)

build(input_shape)[source]
call(pdf)[source]

This function perform the convolution with the fktable and one (DIS) or two (DY-like) pdfs.

Parameters:

pdf (backend tensor) – rank 4 tensor (batch_size, replicas, xgrid, flavours)

Returns:

observables – rank 3 tensor (batchsize, replicas, ndata)

Return type:

backend tensor

abstract gen_mask(basis)[source]
is_pos_polarized()[source]

Check if the given Positivity dataset contains Polarized FK tables by checking name.

abstract pad_fk(fk, mask)[source]
n3fit.layers.observable.compute_float_mask(bool_mask)[source]

Compute a float form of the given boolean mask, that can be contracted over the full flavor axes to obtain a PDF of only the active flavors.

Parameters:

bool_mask (boolean tensor) – mask of the active flavours

Returns:

masked_to_full – float form of mask

Return type:

float tensor

n3fit.layers.observable.compute_pdf_boundary(pdf, q0_value, xgrid, n_std, n_replicas)[source]

Computes the boundary conditions using an input PDF set. This is for instance applied to the polarized fits in which the boundary condition is computed from an unpolarized PDF set. The result is a Tensor object that can be understood by the convolution.

Parameters:
  • pdf (validphys.core.PDF) – a validphys PDF instance to be used as a boundary PDF set

  • q0_value (float) – starting scale of the theory as defined in the FK tables

  • xgrid (np.ndarray) – a grid containing the x-values to be given as input to the PDF

  • n_std (int) – integer representing the shift to the CV w.r.t. the standard deviation

  • n_replicas (int) – number of replicas fitted simultaneously

Returns:

a tensor object that has the same shape of the output of the NN

Return type:

tf.tensor

n3fit.layers.observable.is_unique(list_of_arrays)[source]

Check whether the list of arrays more than one different arrays

n3fit.layers.preprocessing module

class n3fit.layers.preprocessing.Preprocessing(*args, **kwargs)[source]

Bases: MetaLayer

Computes preprocessing factor for the PDF.

This layer generates a factor (1-x)^beta*x^(1-alpha) where both beta and alpha are model paramters that can be trained. If feature scaling is used, the preprocessing factor is x^(1-alpha).

Alpha is initialized uniformly within the ranges allowed in the runcard and then it is only allowed to move between those two values (with a hard wall in each side)

Alpha and, unless feature scaling is used, beta are initialized uniformly within the ranges allowed in the runcard and then they are only allowed to move between those two values (with a hard wall in each side)

Parameters:
  • replica_seeds (List[int]) – list of pre replica seeds for the initializer of the random alpha and beta values

  • flav_info (list) –

    list of dicts containing the information about the fitting of the preprocessing factor This corresponds to the fitting::basis parameter in the nnpdf runcard. The dicts can contain the following fields:

    smallx: range of alpha largex: range of beta trainable: whether these alpha-beta should be trained during the fit

    (defaults to true)

  • large_x (bool) – Whether large x preprocessing factor should be active

build(input_shape)[source]
call(x)[source]

Compute preprocessing prefactor.

Parameters:

x (tensor(shape=[1,N,1]))

Returns:

prefactor

Return type:

tensor(shape=[1,R,N,F])

generate_weight(name: str, kind: str, dictionary: dict, set_to_zero: bool = False)[source]

Generates weights according to the flavour dictionary

Parameters:
  • name (str) – name to be given to the generated weight

  • kind (str) – where to find the limits of the weight in the dictionary

  • dictionary (dict) – dictionary defining the weight, usually one entry from flav_info

  • set_to_zero (bool) – set the weight to constant 0

n3fit.layers.rotations module

This module includes rotation layers

class n3fit.layers.rotations.AddPhoton(*args, **kwargs)[source]

Bases: MetaLayer

Changes the value of the photon component of the PDF to non-zero. The photon idx in the dimension-14 PDF basis of the FKTables is always index 0.

In order to avoid bottlenecks, this layer can only compute the photon for a given fixed shape. In order to change the shape it is necessary to rebuild the photon.

call(pdfs)[source]
register_photon(xgrid)[source]

Compute the photon array of shape (1, replicas, xgrid, 1) and set the layer to be rebuilt

class n3fit.layers.rotations.FkRotation(*args, **kwargs)[source]

Bases: Rotation

Applies a transformation from the dimension-9 evolution basis to the dimension-14 evolution basis used by the fktables.

The input to this layer is a pdf_raw variable which is expected to have a shape (1, None, 9), and it is then rotated to an output (1, None, 14)

class n3fit.layers.rotations.FlavourToEvolution(*args, **kwargs)[source]

Bases: Rotation

Rotates from the flavour basis to the evolution basis.

class n3fit.layers.rotations.ObsRotation(*args, **kwargs)[source]

Bases: MetaLayer

Rotation is a layer used to apply a rotation transformation input transform matrix needs to be np array of N_out*N_in so when the matrix multiplication has taken place you get N_out, … tensor out. If input is a true rotation then N_out=N_in

call(prediction_in)[source]
class n3fit.layers.rotations.Rotation(*args, **kwargs)[source]

Bases: MetaLayer

Rotates the input through some user defined rotation matrix. Given an input matrix M_{m,n} with an input x_{m}, returns y_{n} = x_{m}M_{m,n}

Parameters:
  • rotation_matrix (np.array) – rotation matrix

  • rotation_axis (int) – rotation_axis of input to be rotated

call(x_raw)[source]
is_identity()[source]

Returns true if the rotation is an identity

n3fit.layers.x_operations module

This module contains layers acting on the x-grid input of the NN

The two operations included are:
  • xDivide

  • xIntegrator

The names are self-describing. The only subtlety is that they do not act equally for all flavours. The choice of flavours on which to act in a different way is given as an input argument.

class n3fit.layers.x_operations.xDivide(*args, **kwargs)[source]

Bases: MetaLayer

Create tensor of either 1/x or ones depending on the flavour, to be used to divide some PDFs by x by multiplying with the result.

By default it utilizes the 14-flavour FK basis. In the unpolarized case, one divides [v, v3, v8, v15] which corresponds to indices (3, 4, 5, 6) from the FK basis:

(photon, sigma, g, v, v3, v8, v15, v24, v35, t3, t8, t15, t24, t35)

In the polarized case, only [T3, T8] are divided by x which corresponds to the indices (9, 10).

Parameters:

output_dim: int

dimension of the pdf

div_list: list

list of indices to be divided by x (by default [3, 4, 5, 6]; [v, v3, v8, v15]

call(x)[source]
get_config()[source]

Returns the config of the object.

An object config is a Python dictionary (serializable) containing the information needed to re-instantiate it.

class n3fit.layers.x_operations.xIntegrator(*args, **kwargs)[source]

Bases: MetaLayer

This layer performs a sum of the input layer/tensor on the axis corresponding to the x-grid weighted by the weights of the grid.

The output shape is the input shape with the x-axis removed.

Parameters:
  • grid_weights (np.array) – weights of the grid

  • x_axis (int (default=2)) – axis of the input tensor that corresponds to the x-grid

call(pdf)[source]

Module contents