From 38e1ffdc6cc30350ef656cc216a9378ec6092806 Mon Sep 17 00:00:00 2001 From: juacrumar Date: Mon, 30 Mar 2020 09:52:45 +0200 Subject: [PATCH 01/10] add a square custom activation function --- .../backends/keras_backend/base_layers.py | 28 +++++++++++++++++-- .../layers/{Rotation.py => rotations.py} | 0 2 files changed, 25 insertions(+), 3 deletions(-) rename n3fit/src/n3fit/layers/{Rotation.py => rotations.py} (100%) diff --git a/n3fit/src/n3fit/backends/keras_backend/base_layers.py b/n3fit/src/n3fit/backends/keras_backend/base_layers.py index 35a0ad5e35..00da5cbf66 100644 --- a/n3fit/src/n3fit/backends/keras_backend/base_layers.py +++ b/n3fit/src/n3fit/backends/keras_backend/base_layers.py @@ -1,16 +1,35 @@ """ - For a layer to be used by n3fit it should be contained in the layers dictionary below + This module defines custom base layers to be used by the n3fit + Neural Network. + These layers can use the keras standard set of activation function + or implement their own. + + For a layer to be used by n3fit it should be contained in the `layers` dictionary defined below. This dictionary has the following structure: - 'name of the layer' : ( Layer_class, {dictionary of arguments: defaults} ) + 'name of the layer' : ( Layer_class, {dictionary of arguments: defaults} ) + + In order to add custom activation functions, they must be added to + the `custom_activations` dictionary with the following structure: + + 'name of the activation' : function + + The names of the layer and the activation function are the ones to be used in the n3fit runcard. """ from tensorflow.keras.layers import Dense, Lambda, LSTM, Dropout, Concatenate, concatenate from tensorflow.keras.layers import Dense as KerasDense from tensorflow import expand_dims - from n3fit.backends import MetaLayer +# Custom activation functions +def square_activation(x): + """ Squares the input """ + return x*x + +custom_activations = { + "square" : square_activation + } def LSTM_modified(**kwargs): """ @@ -137,6 +156,9 @@ def base_layer_selector(layer_name, **kwargs): layer_args = layer_tuple[1] for key, value in kwargs.items(): + # Check whether the activation function is a custom one + if key == "activation": + value = custom_activations.get(value, value) if key in layer_args.keys(): layer_args[key] = value diff --git a/n3fit/src/n3fit/layers/Rotation.py b/n3fit/src/n3fit/layers/rotations.py similarity index 100% rename from n3fit/src/n3fit/layers/Rotation.py rename to n3fit/src/n3fit/layers/rotations.py From b239fb053b815b8c8cea7dff2574ac3e726a6350 Mon Sep 17 00:00:00 2001 From: juacrumar Date: Mon, 30 Mar 2020 10:00:13 +0200 Subject: [PATCH 02/10] add flavour basis --- n3fit/src/n3fit/layers/__init__.py | 2 +- n3fit/src/n3fit/layers/rotations.py | 36 +++++++++++++++++++++++++++++ n3fit/src/n3fit/model_gen.py | 21 ++++++++++++----- 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/n3fit/src/n3fit/layers/__init__.py b/n3fit/src/n3fit/layers/__init__.py index 4d87049cec..11091446cd 100644 --- a/n3fit/src/n3fit/layers/__init__.py +++ b/n3fit/src/n3fit/layers/__init__.py @@ -1,5 +1,5 @@ from n3fit.layers.Preprocessing import Preprocessing -from n3fit.layers.Rotation import Rotation +from n3fit.layers.rotations import Rotation, FlavourToEvolution from n3fit.layers.x_operations import xIntegrator, xDivide, xMultiply from n3fit.layers.MSR_Normalization import MSR_Normalization from n3fit.layers.DIS import DIS diff --git a/n3fit/src/n3fit/layers/rotations.py b/n3fit/src/n3fit/layers/rotations.py index caf1e05833..97462c698c 100644 --- a/n3fit/src/n3fit/layers/rotations.py +++ b/n3fit/src/n3fit/layers/rotations.py @@ -1,5 +1,41 @@ +""" + This module includes rotation layers +""" + from n3fit.backends import MetaLayer +class FlavourToEvolution(MetaLayer): + """ + Rotates from the evolution basis to + the evolution basis + """ + # TODO: add a custom __init__ that defines the rotation + + def call(self, x_raw): + # Let's decide that the input is + # u, ubar, d, dbar, s, sbar, c, g + # TODO: it needs to match + # + x_flav = self.transpose(x_raw) + u = x_flav[0] + ubar = x_flav[1] + d = x_flav[2] + dbar = x_flav[3] + s = x_flav[4] + sbar = x_flav[5] + c = x_flav[6] + g = x_flav[7] + cbar = c + sigma = u + ubar + d + dbar + s + sbar + c + cbar + v = u - ubar + d - dbar + s - sbar + c - cbar + v3 = u - ubar - d + dbar + v8 = u - ubar + d - dbar - 2*s + 2*sbar + t3 = u + ubar - d - dbar + t8 = u + ubar + d + dbar - 2*s - 2*sbar + pdf_evol = [sigma, g, v, v3, v8, t3, t8, c+cbar] + ret = self.concatenate(pdf_evol, target_shape=x_raw.shape) + return ret + class Rotation(MetaLayer): """ diff --git a/n3fit/src/n3fit/model_gen.py b/n3fit/src/n3fit/model_gen.py index e418d41527..1061e5137c 100644 --- a/n3fit/src/n3fit/model_gen.py +++ b/n3fit/src/n3fit/model_gen.py @@ -12,7 +12,7 @@ from n3fit.layers import DIS from n3fit.layers import DY from n3fit.layers import Mask -from n3fit.layers import Preprocessing, Rotation +from n3fit.layers import Preprocessing, Rotation, FlavourToEvolution from n3fit.backends import operations from n3fit.backends import losses @@ -271,6 +271,7 @@ def pdfNN_layer_generator( out=14, seed=None, dropout=0.0, + fitbasis=None, # TODO: maybe this can come directly in the basis object? otherwise it is necessary to pass this down from the runcard ): # pylint: disable=too-many-locals """ Generates the PDF model which takes as input a point in x (from 0 to 1) @@ -415,12 +416,20 @@ def dense_me(x): input_shape=(1,), name="pdf_prepro", flav_info=flav_info, seed=preproseed ) - # Apply preprocessing - def layer_fitbasis(x): - return operations.op_multiply([dense_me(x), layer_preproc(x)]) - # Evolution layer - layer_evln = Rotation(input_shape=(last_layer_nodes,), output_dim=out) + layer_evln = Rotation(input_shape=(pre,), output_dim=out) + + # Check what is the output basis of the NN and rotate to evolution basis + if fitbasis == "flavour": # TODO choose the name + basis_rotation = FlavourToEvolution() + else: + # otherwise, assume we are in the evolution basis when we come out of the NN + basis_rotation = lambda x: x + + # Apply preprocessing and basis + def layer_fitbasis(x): + ret = operations.op_multiply([dense_me(x), layer_preproc(x)]) + return basis_rotation(ret) # Rotation layer, changes from the 8-basis to the 14-basis def layer_pdf(x): From 9fed37e70a58014274270e25927e23cc4d5f633c Mon Sep 17 00:00:00 2001 From: juacrumar Date: Wed, 1 Apr 2020 17:59:05 +0200 Subject: [PATCH 03/10] fix rebase --- n3fit/src/n3fit/model_gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/n3fit/src/n3fit/model_gen.py b/n3fit/src/n3fit/model_gen.py index 1061e5137c..91d6ecf80d 100644 --- a/n3fit/src/n3fit/model_gen.py +++ b/n3fit/src/n3fit/model_gen.py @@ -417,7 +417,7 @@ def dense_me(x): ) # Evolution layer - layer_evln = Rotation(input_shape=(pre,), output_dim=out) + layer_evln = Rotation(input_shape=(last_layer_nodes,), output_dim=out) # Check what is the output basis of the NN and rotate to evolution basis if fitbasis == "flavour": # TODO choose the name From bad5872421d289e28fa229adf216675915a47eeb Mon Sep 17 00:00:00 2001 From: tgiani Date: Mon, 6 Apr 2020 17:07:10 +0100 Subject: [PATCH 04/10] adding init and moving rotation to pdfbasis --- n3fit/src/n3fit/layers/rotations.py | 40 +++++++++++++--------------- n3fit/src/n3fit/model_gen.py | 11 +++----- validphys2/src/validphys/pdfbases.py | 21 +++++++++++++++ 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/n3fit/src/n3fit/layers/rotations.py b/n3fit/src/n3fit/layers/rotations.py index 97462c698c..599e6cb183 100644 --- a/n3fit/src/n3fit/layers/rotations.py +++ b/n3fit/src/n3fit/layers/rotations.py @@ -3,36 +3,34 @@ """ from n3fit.backends import MetaLayer +from validphys.pdfbases import flavtoev class FlavourToEvolution(MetaLayer): """ - Rotates from the evolution basis to - the evolution basis + Rotates from the flavour basis to + the evolution basis. """ - # TODO: add a custom __init__ that defines the rotation - + def __init__( + self, + flav_info=None, + **kwargs, + ): + if flav_info is None: + flav_info = [] + self.flav_info = flav_info + super().__init__(**kwargs) + def call(self, x_raw): # Let's decide that the input is # u, ubar, d, dbar, s, sbar, c, g # TODO: it needs to match - # + x_flav = self.transpose(x_raw) - u = x_flav[0] - ubar = x_flav[1] - d = x_flav[2] - dbar = x_flav[3] - s = x_flav[4] - sbar = x_flav[5] - c = x_flav[6] - g = x_flav[7] - cbar = c - sigma = u + ubar + d + dbar + s + sbar + c + cbar - v = u - ubar + d - dbar + s - sbar + c - cbar - v3 = u - ubar - d + dbar - v8 = u - ubar + d - dbar - 2*s + 2*sbar - t3 = u + ubar - d - dbar - t8 = u + ubar + d + dbar - 2*s - 2*sbar - pdf_evol = [sigma, g, v, v3, v8, t3, t8, c+cbar] + #check the fit basis looking at the first flavour in the basis dictionary of the runcard + if(self.flav_info[0]['fl'] == 'u'): + pdf_evol = flavtoev(x_flav) + else: + pdf_evol = x_flav ret = self.concatenate(pdf_evol, target_shape=x_raw.shape) return ret diff --git a/n3fit/src/n3fit/model_gen.py b/n3fit/src/n3fit/model_gen.py index 91d6ecf80d..e89a59f2c9 100644 --- a/n3fit/src/n3fit/model_gen.py +++ b/n3fit/src/n3fit/model_gen.py @@ -271,7 +271,6 @@ def pdfNN_layer_generator( out=14, seed=None, dropout=0.0, - fitbasis=None, # TODO: maybe this can come directly in the basis object? otherwise it is necessary to pass this down from the runcard ): # pylint: disable=too-many-locals """ Generates the PDF model which takes as input a point in x (from 0 to 1) @@ -419,13 +418,9 @@ def dense_me(x): # Evolution layer layer_evln = Rotation(input_shape=(last_layer_nodes,), output_dim=out) - # Check what is the output basis of the NN and rotate to evolution basis - if fitbasis == "flavour": # TODO choose the name - basis_rotation = FlavourToEvolution() - else: - # otherwise, assume we are in the evolution basis when we come out of the NN - basis_rotation = lambda x: x - + # Basis rotation + basis_rotation = FlavourToEvolution(flav_info=flav_info) + # Apply preprocessing and basis def layer_fitbasis(x): ret = operations.op_multiply([dense_me(x), layer_preproc(x)]) diff --git a/validphys2/src/validphys/pdfbases.py b/validphys2/src/validphys/pdfbases.py index 6131b6fe25..dcd9fcafed 100644 --- a/validphys2/src/validphys/pdfbases.py +++ b/validphys2/src/validphys/pdfbases.py @@ -394,3 +394,24 @@ def from_mapping(cls, mapping, *, aliases=None, default_elements=None): r'\bar{d}': {'dbar':1}, 'c': {'c':1}, }) + + +def flavtoev(x_flav): + """Rotates from the flavour to the evolution basis""" + u = x_flav[0] + ubar = x_flav[1] + d = x_flav[2] + dbar = x_flav[3] + s = x_flav[4] + sbar = x_flav[5] + c = x_flav[6] + g = x_flav[7] + cbar = c + sigma = u + ubar + d + dbar + s + sbar + c + cbar + v = u - ubar + d - dbar + s - sbar + c - cbar + v3 = u - ubar - d + dbar + v8 = u - ubar + d - dbar - 2*s + 2*sbar + t3 = u + ubar - d - dbar + t8 = u + ubar + d + dbar - 2*s - 2*sbar + pdf_evol = [sigma, g, v, v3, v8, t3, t8, c+cbar] + return pdf_evol From 96e9c250cbd27c86e7528dbdf6f2153b40608af1 Mon Sep 17 00:00:00 2001 From: tgiani Date: Tue, 7 Apr 2020 16:51:00 +0100 Subject: [PATCH 05/10] implementation of rotation function in pdfbases --- .../n3fit/backends/keras_backend/MetaLayer.py | 3 ++ n3fit/src/n3fit/layers/rotations.py | 28 ++++------ validphys2/src/validphys/pdfbases.py | 54 +++++++++++++------ 3 files changed, 51 insertions(+), 34 deletions(-) diff --git a/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py b/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py index 156d22a87b..059fb933b1 100644 --- a/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py +++ b/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py @@ -191,3 +191,6 @@ def permute_dimensions(self, tensor, permutation, **kwargs): does the permutation: axis_0 -> axis_1, axis_1 -> axis_0, axis_2 -> axis_2 """ return K.permute_dimensions(tensor, permutation, **kwargs) + + def reshape(self, tensor, target_shape): + return tf.reshape(tensor, target_shape) \ No newline at end of file diff --git a/n3fit/src/n3fit/layers/rotations.py b/n3fit/src/n3fit/layers/rotations.py index 599e6cb183..44779833b6 100644 --- a/n3fit/src/n3fit/layers/rotations.py +++ b/n3fit/src/n3fit/layers/rotations.py @@ -1,38 +1,28 @@ """ This module includes rotation layers """ - from n3fit.backends import MetaLayer -from validphys.pdfbases import flavtoev +from validphys.pdfbases import rotation class FlavourToEvolution(MetaLayer): """ Rotates from the flavour basis to - the evolution basis. + the evolution basis. """ def __init__( self, - flav_info=None, + flav_info, **kwargs, ): - if flav_info is None: - flav_info = [] - self.flav_info = flav_info + rotation_matrix = rotation(flav_info) + self.rotation_matrix = self.np_to_tensor(rotation_matrix) super().__init__(**kwargs) - def call(self, x_raw): - # Let's decide that the input is - # u, ubar, d, dbar, s, sbar, c, g - # TODO: it needs to match - + def call(self, x_raw): x_flav = self.transpose(x_raw) - #check the fit basis looking at the first flavour in the basis dictionary of the runcard - if(self.flav_info[0]['fl'] == 'u'): - pdf_evol = flavtoev(x_flav) - else: - pdf_evol = x_flav - ret = self.concatenate(pdf_evol, target_shape=x_raw.shape) - return ret + pdf_evol = self.tensor_product(self.rotation_matrix, x_flav, 1) + return self.reshape(pdf_evol, x_raw.shape) + class Rotation(MetaLayer): diff --git a/validphys2/src/validphys/pdfbases.py b/validphys2/src/validphys/pdfbases.py index dcd9fcafed..a049e74b83 100644 --- a/validphys2/src/validphys/pdfbases.py +++ b/validphys2/src/validphys/pdfbases.py @@ -396,22 +396,46 @@ def from_mapping(cls, mapping, *, aliases=None, default_elements=None): }) -def flavtoev(x_flav): - """Rotates from the flavour to the evolution basis""" - u = x_flav[0] - ubar = x_flav[1] - d = x_flav[2] - dbar = x_flav[3] - s = x_flav[4] - sbar = x_flav[5] - c = x_flav[6] - g = x_flav[7] - cbar = c - sigma = u + ubar + d + dbar + s + sbar + c + cbar - v = u - ubar + d - dbar + s - sbar + c - cbar +def rotation(flav_info): + """Returnd a rotation matrix which takes from the flavour to the evolution basis, + from (u, ubar, d, dbar, s, sbar, c, g) to (sigma, g, v, v3, v8, t3, t8, cp) + with + cp = c + cbar = 2c + and + sigma = u + ubar + d + dbar + s + sbar + cp + v = u - ubar + d - dbar + s - sbar + c - cbar v3 = u - ubar - d + dbar v8 = u - ubar + d - dbar - 2*s + 2*sbar t3 = u + ubar - d - dbar t8 = u + ubar + d + dbar - 2*s - 2*sbar - pdf_evol = [sigma, g, v, v3, v8, t3, t8, c+cbar] - return pdf_evol + + If the input is already in the evolution basis it returns the identity. + """ + sigma = {'u': 1, 'ubar': 1, 'd': 1, 'dbar': 1, 's': 1, 'sbar': 1, 'c': 2, 'g': 0 } + v = {'u': 1, 'ubar': -1, 'd': 1, 'dbar': -1, 's': 1, 'sbar': -1, 'c': 0, 'g': 0 } + v3 = {'u': 1, 'ubar': -1, 'd': -1, 'dbar': 1, 's': 0, 'sbar': 0, 'c': 0, 'g': 0 } + v8 = {'u': 1, 'ubar': -1, 'd': 1, 'dbar': -1, 's': -2, 'sbar': 2, 'c': 0, 'g': 0 } + t3 = {'u': 1, 'ubar': 1, 'd': -1, 'dbar': -1, 's': 0, 'sbar': 0, 'c': 0, 'g': 0 } + t8 = {'u': 1, 'ubar': 1, 'd': 1, 'dbar': 1, 's': -2, 'sbar': -2, 'c': 0, 'g': 0 } + cp = {'u': 0, 'ubar': 0, 'd': 0, 'dbar': 0, 's': 0, 'sbar': 0, 'c': 2, 'g': 0 } + g = {'u': 0, 'ubar': 0, 'd': 0, 'dbar': 0, 's': 0, 'sbar': 0, 'c': 0, 'g': 1 } + flist = [sigma, g, v, v3, v8, t3, t8, cp] + + evol_basis = False + mat = [] + for f in flist: + for flav_dict in flav_info: + try: + flav_name = flav_dict["fl"] + mat.append(f[flav_name]) + # if one of the keys in the dictionary is not a key in flist + # it means we are already in the evolution basis + except KeyError: + evol_basis = True + break + if evol_basis: + mat = np.identity(8) + break + + mat = np.asarray(mat) + return mat.reshape(8,8) From 7b5b01d238f8d68a1b93631324b8bbaa68c3189b Mon Sep 17 00:00:00 2001 From: tgiani Date: Tue, 7 Apr 2020 17:21:13 +0100 Subject: [PATCH 06/10] removing reshape of the output --- n3fit/src/n3fit/backends/keras_backend/MetaLayer.py | 3 +-- n3fit/src/n3fit/layers/rotations.py | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py b/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py index 059fb933b1..a91fd761d8 100644 --- a/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py +++ b/n3fit/src/n3fit/backends/keras_backend/MetaLayer.py @@ -192,5 +192,4 @@ def permute_dimensions(self, tensor, permutation, **kwargs): """ return K.permute_dimensions(tensor, permutation, **kwargs) - def reshape(self, tensor, target_shape): - return tf.reshape(tensor, target_shape) \ No newline at end of file + \ No newline at end of file diff --git a/n3fit/src/n3fit/layers/rotations.py b/n3fit/src/n3fit/layers/rotations.py index 44779833b6..f4a9fe19b9 100644 --- a/n3fit/src/n3fit/layers/rotations.py +++ b/n3fit/src/n3fit/layers/rotations.py @@ -18,13 +18,10 @@ def __init__( self.rotation_matrix = self.np_to_tensor(rotation_matrix) super().__init__(**kwargs) - def call(self, x_raw): - x_flav = self.transpose(x_raw) - pdf_evol = self.tensor_product(self.rotation_matrix, x_flav, 1) - return self.reshape(pdf_evol, x_raw.shape) + def call(self, x_raw): + return self.tensor_product(x_raw, self.rotation_matrix, 1) - class Rotation(MetaLayer): """ Applies a transformation from the dimension-8 fit basis From 958a137c06a5ed2cec792a3f7948ec57daa4228f Mon Sep 17 00:00:00 2001 From: tgiani Date: Sun, 19 Apr 2020 14:25:52 +0100 Subject: [PATCH 07/10] small edit to run fit without sum rules --- n3fit/src/n3fit/ModelTrainer.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/n3fit/src/n3fit/ModelTrainer.py b/n3fit/src/n3fit/ModelTrainer.py index ea815317f8..a37cf13140 100644 --- a/n3fit/src/n3fit/ModelTrainer.py +++ b/n3fit/src/n3fit/ModelTrainer.py @@ -12,7 +12,7 @@ import numpy as np import n3fit.model_gen as model_gen import n3fit.msr as msr_constraints -from n3fit.backends import MetaModel, clear_backend_state +from n3fit.backends import MetaModel, clear_backend_state, operations from n3fit.stopping import Stopping log = logging.getLogger(__name__) @@ -442,15 +442,18 @@ def _generate_pdf( dropout=dropout, ) - integrator_input = None if self.impose_sumrule: # Impose the sumrule # Inyect here momentum sum rule, effecively modifying layer_pdf layer_pdf, integrator_input = msr_constraints.msr_impose( layers["fitbasis"], layer_pdf ) - self.input_list.append(integrator_input) + else: + nx = int(2e3) + xgrid, dum = msr_constraints.gen_integration_input(nx) + integrator_input = operations.numpy_to_input(xgrid) + self.input_list.append(integrator_input) self.layer_pdf = layer_pdf return layers, integrator_input From 4ce3775d6e12de07921f33bd127721f5665f8ca5 Mon Sep 17 00:00:00 2001 From: tgiani Date: Tue, 21 Apr 2020 17:38:24 +0100 Subject: [PATCH 08/10] preprocessing layer --- n3fit/src/n3fit/layers/Preprocessing.py | 37 +++++++++++++------------ 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/n3fit/src/n3fit/layers/Preprocessing.py b/n3fit/src/n3fit/layers/Preprocessing.py index 6a3bb29dc7..0d85b9d98c 100644 --- a/n3fit/src/n3fit/layers/Preprocessing.py +++ b/n3fit/src/n3fit/layers/Preprocessing.py @@ -44,14 +44,14 @@ def __init__( self.flav_info = flav_info self.seed = seed self.initializer = initializer - self.kernel = [] + self.kernel = {} # super(MetaLayer, self).__init__(**kwargs) super().__init__(**kwargs) def generate_weight(self, weight_name, kind, dictionary): """ Generates weights according to the flavour dictionary and adds them - to the kernel list of the class + to the kernel dictionary of the class Parameters ---------- @@ -84,12 +84,15 @@ def generate_weight(self, weight_name, kind, dictionary): trainable=trainable, constraint=weight_constraint, ) - self.kernel.append(newpar) + self.kernel[weight_name] = newpar def build(self, input_shape): # Run through the whole basis for flav_dict in self.flav_info: flav_name = flav_dict["fl"] + # If there are antiquarks don't generate weights for them + if "bar" in flav_name: + continue alpha_name = f"alpha_{flav_name}" beta_name = f"beta_{flav_name}" self.generate_weight(alpha_name, "smallx", flav_dict) @@ -99,17 +102,17 @@ def build(self, input_shape): def call(self, inputs, **kwargs): x = inputs - pdf_raw = self.concatenate( - [ - x ** (1 - self.kernel[0][0]) * (1 - x) ** self.kernel[1][0], # sigma - x ** (1 - self.kernel[2][0]) * (1 - x) ** self.kernel[3][0], # g - x ** (1 - self.kernel[4][0]) * (1 - x) ** self.kernel[5][0], # v - x ** (1 - self.kernel[6][0]) * (1 - x) ** self.kernel[7][0], # v3 - x ** (1 - self.kernel[8][0]) * (1 - x) ** self.kernel[9][0], # v8 - x ** (1 - self.kernel[10][0]) * (1 - x) ** self.kernel[11][0], # t3 = sigma - x ** (1 - self.kernel[12][0]) * (1 - x) ** self.kernel[13][0], # t8 = sigma - x ** (1 - self.kernel[14][0]) * (1 - x) ** self.kernel[15][0], # t15 c- - ], - axis=-1, - ) - return pdf_raw + pdf_raw = [] + # For each entry of the basis build the preprocessing factor + for flav_dict in self.flav_info: + flav_name = flav_dict['fl'] + # If the entry is an antiquark, consider the same weights as the corresponding quark + if "bar" in flav_name: + flav_name = flav_name.replace('bar','') + alpha_name = f"alpha_{flav_name}" + beta_name = f"beta_{flav_name}" + alpha = self.kernel[alpha_name][0] + beta = self.kernel[beta_name][0] + pdf_raw.append( x ** (1 - alpha) * (1 - x) ** beta ) + + return self.concatenate(pdf_raw) From 43269114eafc1b703919de9a7efe2cc1e65af531 Mon Sep 17 00:00:00 2001 From: tgiani Date: Wed, 22 Apr 2020 14:08:04 +0100 Subject: [PATCH 09/10] second go on preprocessing --- n3fit/src/n3fit/layers/Preprocessing.py | 52 +++++++++++++++++-------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/n3fit/src/n3fit/layers/Preprocessing.py b/n3fit/src/n3fit/layers/Preprocessing.py index 0d85b9d98c..ab9c433f1a 100644 --- a/n3fit/src/n3fit/layers/Preprocessing.py +++ b/n3fit/src/n3fit/layers/Preprocessing.py @@ -36,6 +36,7 @@ def __init__( flav_info=None, seed=0, initializer="random_uniform", + flavbasis=False, **kwargs, ): self.output_dim = output_dim @@ -44,14 +45,15 @@ def __init__( self.flav_info = flav_info self.seed = seed self.initializer = initializer - self.kernel = {} + self.flavbasis=flavbasis + self.kernel = [] # super(MetaLayer, self).__init__(**kwargs) super().__init__(**kwargs) def generate_weight(self, weight_name, kind, dictionary): """ Generates weights according to the flavour dictionary and adds them - to the kernel dictionary of the class + to the kernel list of the class Parameters ---------- @@ -84,7 +86,7 @@ def generate_weight(self, weight_name, kind, dictionary): trainable=trainable, constraint=weight_constraint, ) - self.kernel[weight_name] = newpar + self.kernel.append(newpar) def build(self, input_shape): # Run through the whole basis @@ -92,6 +94,7 @@ def build(self, input_shape): flav_name = flav_dict["fl"] # If there are antiquarks don't generate weights for them if "bar" in flav_name: + self.flavbasis=True continue alpha_name = f"alpha_{flav_name}" beta_name = f"beta_{flav_name}" @@ -102,17 +105,32 @@ def build(self, input_shape): def call(self, inputs, **kwargs): x = inputs - pdf_raw = [] - # For each entry of the basis build the preprocessing factor - for flav_dict in self.flav_info: - flav_name = flav_dict['fl'] - # If the entry is an antiquark, consider the same weights as the corresponding quark - if "bar" in flav_name: - flav_name = flav_name.replace('bar','') - alpha_name = f"alpha_{flav_name}" - beta_name = f"beta_{flav_name}" - alpha = self.kernel[alpha_name][0] - beta = self.kernel[beta_name][0] - pdf_raw.append( x ** (1 - alpha) * (1 - x) ** beta ) - - return self.concatenate(pdf_raw) + if self.flavbasis: + pdf_raw = self.concatenate( + [ + x ** (1 - self.kernel[0][0]) * (1 - x) ** self.kernel[1][0], # u + x ** (1 - self.kernel[0][0]) * (1 - x) ** self.kernel[1][0], # ubar + x ** (1 - self.kernel[2][0]) * (1 - x) ** self.kernel[3][0], # d + x ** (1 - self.kernel[2][0]) * (1 - x) ** self.kernel[3][0], # dbar + x ** (1 - self.kernel[4][0]) * (1 - x) ** self.kernel[5][0], # s + x ** (1 - self.kernel[4][0]) * (1 - x) ** self.kernel[5][0], # sbar + x ** (1 - self.kernel[6][0]) * (1 - x) ** self.kernel[7][0], # c + x ** (1 - self.kernel[8][0]) * (1 - x) ** self.kernel[9][0], # g + ], + axis=-1, + ) + else: + pdf_raw = self.concatenate( + [ + x ** (1 - self.kernel[0][0]) * (1 - x) ** self.kernel[1][0], # sigma + x ** (1 - self.kernel[2][0]) * (1 - x) ** self.kernel[3][0], # g + x ** (1 - self.kernel[4][0]) * (1 - x) ** self.kernel[5][0], # v + x ** (1 - self.kernel[6][0]) * (1 - x) ** self.kernel[7][0], # v3 + x ** (1 - self.kernel[8][0]) * (1 - x) ** self.kernel[9][0], # v8 + x ** (1 - self.kernel[10][0]) * (1 - x) ** self.kernel[11][0], # t3 = sigma + x ** (1 - self.kernel[12][0]) * (1 - x) ** self.kernel[13][0], # t8 = sigma + x ** (1 - self.kernel[14][0]) * (1 - x) ** self.kernel[15][0], # t15 c- + ], + axis=-1, + ) + return pdf_raw From 56f8e8d057f1fcf1825211b05db40206f6a6f9d0 Mon Sep 17 00:00:00 2001 From: tgiani Date: Sat, 25 Apr 2020 15:37:28 +0100 Subject: [PATCH 10/10] adding subtraction at x=1 --- n3fit/src/n3fit/backends/keras_backend/operations.py | 4 ++++ n3fit/src/n3fit/model_gen.py | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/n3fit/src/n3fit/backends/keras_backend/operations.py b/n3fit/src/n3fit/backends/keras_backend/operations.py index 2ba4156b15..45a1f9e9b2 100644 --- a/n3fit/src/n3fit/backends/keras_backend/operations.py +++ b/n3fit/src/n3fit/backends/keras_backend/operations.py @@ -185,3 +185,7 @@ def op_smn(o_list, **kwargs): numer = op_add(o_list[:2]) denom = op_add(o_list[2:]) return op_ratio([numer, denom], **kwargs) + +def m_tensor_ones_like(*args, **kwargs): + return K.ones_like(*args, **kwargs) + diff --git a/n3fit/src/n3fit/model_gen.py b/n3fit/src/n3fit/model_gen.py index e89a59f2c9..f883da0279 100644 --- a/n3fit/src/n3fit/model_gen.py +++ b/n3fit/src/n3fit/model_gen.py @@ -400,14 +400,19 @@ def pdfNN_layer_generator( def dense_me(x): """ Takes an input tensor `x` and applies all layers from the `list_of_pdf_layers` in order """ + x0 = operations.m_tensor_ones_like(x) if inp == 1: curr_fun = list_of_pdf_layers[0](x) + curr_fun0 = list_of_pdf_layers[0](x0) else: curr_fun = list_of_pdf_layers[0](add_log(x)) + curr_fun0 = list_of_pdf_layers[0](add_log(x0)) for dense_layer in list_of_pdf_layers[1:]: curr_fun = dense_layer(curr_fun) - return curr_fun + curr_fun0 = dense_layer(curr_fun0) + res = operations.op_subtract([curr_fun,curr_fun0]) + return res # Preprocessing layer (will be multiplied to the last of the denses) preproseed = seed + number_of_layers