From 3079463bc0ca4f880c3c6c86e919e6f885320205 Mon Sep 17 00:00:00 2001 From: Luc Giffon <luc.giffon@lis-lab.fr> Date: Fri, 12 Jul 2019 15:50:35 +0200 Subject: [PATCH] add documentation to python files --- keras_kernel_functions.py | 28 +++++++++++++++++++++++++--- nystrom_layer.py | 21 +++++++++++++++++++-- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/keras_kernel_functions.py b/keras_kernel_functions.py index 9ebd4cb..b967df1 100644 --- a/keras_kernel_functions.py +++ b/keras_kernel_functions.py @@ -19,7 +19,7 @@ def keras_linear_kernel(args, normalize=True, tanh_activation=False): :param args: list of size 2 containing x and y :param normalize: if True, normalize the input with l2 before computing the kernel function :param tanh_activation: if True apply tanh activation to the output - :return: + :return: The linear kernel between args[0] and args[1] """ X = args[0] Y = args[1] @@ -35,6 +35,17 @@ def keras_linear_kernel(args, normalize=True, tanh_activation=False): def keras_chi_square_CPD(args, epsilon=None, tanh_activation=True, normalize=False): + """ + Chi square kernel (equivalent to `additive_chi2_kernel` in scikit-learn): + + $k(x, y) = -Sum [(x - y)^2 / (x + y)]$ + + :param args: list of size 2 containing x and y + :param epsilon: very small value to add to the denominator so that we do not have zeros here + :param tanh_activation: if True apply tanh activation to the output + :param normalize: if True, normalize the input with l2 before computing the kernel function + :return: The chi square kernel between args[0] and args[1] + """ X = args[0] Y = args[1] if normalize: @@ -59,6 +70,17 @@ def keras_chi_square_CPD(args, epsilon=None, tanh_activation=True, normalize=Fal def keras_chi_square_CPD_exp(args, gamma, epsilon=None, tanh_activation=False, normalize=True): + """ + Exponential chi square kernel (equivalent to `chi2_kernel` in scikit-learn): + + $k(x, y) = exp(-gamma Sum [(x - y)^2 / (x + y)])$ + + :param args: list of size 2 containing x and y + :param epsilon: very small value to add to the denominator so that we do not have zeros here + :param tanh_activation: if True apply tanh activation to the output + :param normalize: if True, normalize the input with l2 before computing the kernel function + :return: The exponential chi square kernel between args[0] and args[1] + """ result = keras_chi_square_CPD(args, epsilon, tanh_activation, normalize) result *= gamma return K.exp(result) @@ -68,12 +90,12 @@ def keras_rbf_kernel(args, gamma, normalize=True, tanh_activation=False): """ Compute the rbf kernel between each entry of X and each line of Y. - tf_rbf_kernel(x, y, gamma) = exp(- (||x - y||^2 * gamma)) + $(x, y, gamma) = exp(- (||x - y||^2 * gamma))$ :param X: A tensor of size n times d :param Y: A tensor of size m times d :param gamma: The bandwith of the kernel - :return: + :return: The RBF kernel between args[0] and args[1] """ X = args[0] Y = args[1] diff --git a/nystrom_layer.py b/nystrom_layer.py index ebeb7f5..a610db6 100644 --- a/nystrom_layer.py +++ b/nystrom_layer.py @@ -10,7 +10,18 @@ from keras.preprocessing.image import ImageDataGenerator from keras_kernel_functions import keras_linear_kernel -def datagen_fixed_batch_size(x, y, x_sub=None, p_datagen=ImageDataGenerator()): +def datagen_fixed_batch_size(x, y, batch_size, x_sub=None, p_datagen=ImageDataGenerator()): + """ + Wrap a data generator so that: + - it always output batches of the same size + - it gives a subsample along with each batch + + :param x: observation data + :param y: label data + :param x_sub: list of base of subsample (each base must be of size batch_size) + :param p_datagen: the initial data generator to wrap + :return: + """ if x_sub is None: x_sub = [] for x_batch, y_batch in p_datagen.flow(x, y, batch_size=batch_size): @@ -59,6 +70,8 @@ def init_number_subsample_bases(nys_size, batch_size): return quotient + 1, batch_size - remaining if __name__ == "__main__": + # model meta parameters + # --------------------- batch_size = 128 epochs = 1 num_classes = 10 @@ -126,11 +139,15 @@ if __name__ == "__main__": # weight matrix of the nystrom layer input_classifier = Dense(nys_size, use_bias=False, activation='linear')(kernel_vector) # metric matrix of the Nyström layer + # final softmax classification layer + # ---------------------------------- classif = Dense(num_classes, activation="softmax")(input_classifier) + # finalization of model, compilation and training + # ----------------------------------------------- model = Model([input_x] + input_repr_subsample, [classif]) adam = Adam(lr=.1) model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy']) - model.fit_generator(datagen_fixed_batch_size(x_train, y_train, list_subsample_bases, datagen), + model.fit_generator(datagen_fixed_batch_size(x_train, y_train, batch_size, list_subsample_bases, datagen), steps_per_epoch=int(x_train.shape[0] / batch_size), epochs=epochs) -- GitLab