Skip to content
Snippets Groups Projects
Commit 7074d6f7 authored by Luc Giffon's avatar Luc Giffon
Browse files

WIP fonctions noyau et deepstrom layer en keras

parent c44bc7b1
No related branches found
No related tags found
No related merge requests found
import tensorflow as tf
from skluc.main.tensorflow_.utils import replace_nan
def keras_linear_kernel(args):
X = args[0]
Y = args[1]
X = tf.nn.l2_normalize(X, axis=-1)
Y = tf.nn.l2_normalize(Y, axis=-1)
return tf.matmul(X, tf.transpose(Y))
def keras_chi_square_CPD(args):
X = args[0]
Y = args[1]
# X = tf.nn.l2_normalize(X, axis=-1)
# Y = tf.nn.l2_normalize(Y, axis=-1)
# the drawing of the matrix X expanded looks like a wall
wall = tf.expand_dims(X, axis=1)
# the drawing of the matrix Y expanded looks like a floor
floor = tf.expand_dims(Y, axis=0)
numerator = tf.square((wall - floor))
denominator = wall + floor
quotient = numerator / denominator
quotient_without_nan = replace_nan(quotient)
K = - tf.reduce_sum(quotient_without_nan, axis=2)
return K
if __name__ == '__main__':
a = tf.Constant(value=0)
\ No newline at end of file
from skluc.main.tensorflow_.kernel_approximation import fastfood_layer as fastfood_layer
from skluc.main.tensorflow_.kernel_approximation import nystrom_layer as nystrom_layer
"""
Convnet with nystrom approximation of the feature map.
"""
import time as t
import numpy as np
import keras
from sklearn.metrics.pairwise import rbf_kernel, linear_kernel, additive_chi2_kernel, chi2_kernel, laplacian_kernel
import skluc.main.data.mldatasets as dataset
from skluc.main.tensorflow_.kernel import tf_rbf_kernel, tf_chi_square_CPD, tf_chi_square_CPD_exp, tf_laplacian_kernel, tf_linear_kernel
from skluc.main.utils import logger
import tensorflow as tf
class DeepstromLayerEndToEnd(keras.layers.Layer):
def __init__(self,
subsample_size,
kernel_name,
out_dim=None,
activation=None,
sum_of_kernels=False,
stack_of_kernels=False,
kernel_dict={}
):
def init_kernel():
if kernel_name == "rbf":
kernel_fct = rbf_kernel
tf_kernel_fct = tf_rbf_kernel
elif kernel_name == "linear":
kernel_fct = linear_kernel
tf_kernel_fct = tf_linear_kernel
elif kernel_name == "chi2_cpd":
kernel_fct = additive_chi2_kernel
tf_kernel_fct = tf_chi_square_CPD
elif kernel_name == "chi2_exp_cpd":
kernel_fct = chi2_kernel
tf_kernel_fct = tf_chi_square_CPD_exp
elif kernel_name == "chi2_pd":
raise NotImplementedError("Bien verifier que ce code ne fait pas bordel")
elif kernel_name == "laplacian":
tf_kernel_fct = tf_laplacian_kernel
kernel_fct = laplacian_kernel
else:
raise ValueError("Unknown kernel name: {}".format(kernel_name))
return kernel_name, kernel_fct, tf_kernel_fct, kernel_dict
def init_output_dim(subsample_size):
if out_dim is not None and out_dim > subsample_size:
logger.debug("Output dim is greater than deepstrom subsample size. Aborting.")
exit()
elif out_dim is None:
return subsample_size
else:
return out_dim
def init_activation():
if activation == "tan":
activation_fct = tf.nn.tanh
elif activation == "relu":
activation_fct = tf.nn.relu
else:
activation_fct = activation
return activation_fct
super().__init__()
self.__subsample_size = subsample_size
self.__sum_of_kernels = sum_of_kernels
self.__stack_of_kernels = stack_of_kernels
self.__kernel_name, self.__kernel_fct, self.__tf_kernel_fct, self.__kernel_dict = init_kernel()
self.__output_dim = init_output_dim(self.__subsample_size)
self.__activation = init_activation()
self.__W_matrix = None
logger.info("Selecting deepstrom layer function with "
"subsample size = {}, "
"output_dim = {}, "
"{} activation function "
"and kernel = {}"
.format(self.__subsample_size,
self.__output_dim,
"with" if self.__activation else "without",
self.__kernel_name))
def build(self, input_shape):
if self.__output_dim != 0:
# outputdim == 0 means there is no W matrix and the kernel vector is directly added as input to
# the next layer
self.__W_matrix = self.add_weight(
name="W_nystrom",
shape=[self.__subsample_size, self.__output_dim],
initializer='glorot_uniform',
trainable=True
)
super(DeepstromLayerEndToEnd, self).build(input_shape)
@property
def output_dim(self):
return self.__output_dim
def call(self, inputs, **kwargs):
if type(inputs) is not list:
raise ValueError("Inputs of layer deepstrom should be a list")
if len(inputs[0].shape) != 2:
raise ValueError(f"Input x should be 2D but it is {len(inputs[0].shape)}D")
if len(inputs[1].shape) != 2:
raise ValueError(f"Input subsample should be 2D but it is {len(inputs[1].shape)}D")
if inputs[1].shape[0] != self.__subsample_size:
raise ValueError(f"Subsample should be of size {self.__subsample_size}")
if inputs[0][0].shape[0] != inputs[1][0].shape[0]:
raise ValueError(f"Input and subsample should have the same dimension")
input_x = inputs[0]
input_sub = inputs[1]
input_x = tf.nn.l2_normalize(input_x, axis=-1)
input_sub = tf.nn.l2_normalize(input_sub, axis=-1)
with tf.name_scope("NystromLayer"):
with tf.name_scope("kernel_vec"):
kernel_vector = self.__tf_kernel_fct(input_x, input_sub, **self.__kernel_dict)
tf.summary.histogram("kernel_vector", kernel_vector)
if self.__output_dim != 0:
out = tf.matmul(kernel_vector, self.__W_matrix)
tf.summary.histogram("W_matrix", self.__W_matrix)
else:
out = kernel_vector
if self.__activation is not None:
out = self.__activation(out)
return out
def compute_output_shape(self, input_shape):
return (input_shape[0], self.output_dim)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment