Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions n3fit/src/n3fit/backends/keras_backend/MetaLayer.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,26 @@ def builder_helper(
self.weight_inits.append((kernel, initializer))
return kernel

def get_weight_by_name(self, weight_name, internal_count=0):
"""
Returns a weight of the layer by name, returns None if the layer does not include
the named weight.

Note that internally weights of a layer are prefaced by the name of the layer, this
should not be added to the input of this function. i.e., if the internal name is
"layer/weight:0", the argument to this method should be just "weight".

Parameters
----------
weight_name: str
Name of the weight
"""
check_name = f"{self.name}/{weight_name}:{internal_count}"
for weight in self.weights:
if weight.name == check_name:
return weight
return None

# Implemented initializers
@staticmethod
def init_constant(value):
Expand Down
2 changes: 1 addition & 1 deletion n3fit/src/n3fit/io/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def jsonfit(stopping_object, pdf_object, tr_chi2, vl_chi2, true_chi2, timing):
"""
all_info = {}
# Generate preprocessing information
all_info["preprocessing"] = ""
all_info["preprocessing"] = pdf_object.get_preprocessing_factors()
# .fitinfo-like info
all_info["epoch_of_the_stop"] = stopping_object.epoch_of_the_stop
all_info["best_epoch"] = stopping_object.e_best_chi2
Expand Down
2 changes: 1 addition & 1 deletion n3fit/src/n3fit/performfit.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ def performfit(
)

# Create a pdf instance
pdf_instance = N3PDF(pdf_model)
pdf_instance = N3PDF(pdf_model, fit_basis=fitting.get("basis"))

# Generate the writer wrapper
writer_wrapper = WriterWrapper(
Expand Down
61 changes: 54 additions & 7 deletions n3fit/src/n3fit/vpinterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,23 @@


class N3PDF(PDF):
def __init__(self, pdf_model, name="n3fit"):
"""
Creates a N3PDF object, extension of the validphys PDF object to perform calculation
with a n3fit generated model.

Parameters
----------
pdf_model: :py:class:`n3fit.backends.MetaModel`
PDF trained with n3fit, x -> f(x)_{i} where i are the flavours in the evol basis
fit_basis: list(dict)
basis of the training, used for reporting
name: str
name of the N3PDF object
"""

def __init__(self, pdf_model, fit_basis=None, name="n3fit"):
self.model = pdf_model
self.fit_basis = fit_basis
self.basis = check_basis("evolution", EVOL_LIST)["basis"]
# Set the number of members to two for legacy compatibility
# in this case replica 0 and replica 1 are the same
Expand All @@ -64,20 +79,52 @@ def load(self):
"""
return self

def get_nn_weights(self):
"""Outputs all weights of the NN as numpy.ndarrays """
return self.model.get_weights()

def get_preprocessing_factors(self):
"""Loads the preprocessing alpha and beta arrays from the PDF trained model.
If a ``fit_basis`` given in the format of ``n3fit`` runcards is given it will be used
to generate a new dictionary with the names, the exponent and whether they are trainable
otherwise outputs a Nx2 array where [:,0] are alphas and [:,1] betas
"""
preprocessing_layer = self.model.get_layer("pdf_prepro")
if self.fit_basis is not None:
output_dictionaries = []
for d in self.fit_basis:
flavour = d["fl"]
alpha = preprocessing_layer.get_weight_by_name(f"alpha_{flavour}")
beta = preprocessing_layer.get_weight_by_name(f"beta_{flavour}")
if alpha is not None:
alpha = float(alpha.numpy())
Comment thread
siranipour marked this conversation as resolved.
if beta is not None:
beta = float(beta.numpy())
output_dictionaries.append(
{
"fl": flavour,
"smallx": alpha,
"largex": beta,
"trainable": d.get("trainable", True),
}
)
alphas_and_betas = output_dictionaries
return alphas_and_betas

def __call__(self, xarr, flavours=None):
"""Uses the internal model to produce pdf values.
The output is on the evolution basis.

Parameters
----------
xarr: numpy.array
xarr: numpy.ndarray
x-points with shape (xgrid_size,) (size-1 dimensions are removed)
flavours: list
list of flavours to output

Returns
-------
numpy.array
numpy.ndarray
(xgrid_size, flavours) pdf result
"""
if flavours is None:
Expand All @@ -95,16 +142,16 @@ def grid_values(self, flavours, xarr, qmat=None):
"""
Parameters
----------
flavours: numpy.array
flavours: numpy.ndarray
flavours to compute
xarr: numpy.array
xarr: numpy.ndarray
x-points to compute, dim: (xgrid_size,)
qmat: numpy.array
qmat: numpy.ndarray
q-points to compute (not used by n3fit, used only for shaping purposes)

Returns
------
numpy.array
numpy.ndarray
array of shape (1, flavours, xgrid_size, qmat) with the values of the ``pdf_model``
evaluated in ``xarr``
"""
Expand Down