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

moving the fastfood layer to scikit luc + change usage of mnist and cifar...

moving the fastfood layer to scikit luc + change usage of mnist and cifar datasets in deepfriedconvnetcifar10 and mnsi
parent 08bf1947
No related branches found
No related tags found
No related merge requests found
import tensorflow as tf import tensorflow as tf
import numpy as np import numpy as np
from sklearn.preprocessing import LabelBinarizer
import skluc.mldatasets as dataset import skluc.mldatasets as dataset
from fasfood_layer import fast_food
import matplotlib.pyplot as plt
IMAGE_SIZE = 24 IMAGE_SIZE = 24
enc = LabelBinarizer()
cifar = dataset.Cifar10Dataset()
cifar_d = cifar.load()
cifar_d = cifar.to_image()
X_train, Y_train = cifar_d["train"]
X_test, Y_test = cifar_d["test"]
X_train = np.array(X_train / 255)
enc.fit(Y_train)
Y_train = np.array(enc.transform(Y_train))
X_test = np.array(X_test / 255)
Y_test = np.array(enc.transform(Y_test))
X_train = X_train.astype(np.float32)
permut = np.random.permutation(X_train.shape[0])
val_size = 5000 val_size = 5000
X_val = X_train[permut[:val_size]] cifar = dataset.Cifar10Dataset(validation_size=val_size)
X_train = X_train[permut[val_size:]] cifar.load()
Y_val = Y_train[permut[:val_size]] cifar.normalize()
Y_train = Y_train[permut[val_size:]] cifar.to_one_hot()
X_test = X_test.astype(np.float32) cifar.data_astype(np.float32)
Y_train = Y_train.astype(np.float32) cifar.labels_astype(np.float32)
Y_test = Y_test.astype(np.float32) X_train, Y_train = cifar.train
X_test, Y_test = cifar.test
X_val, Y_val = cifar.validation
def distorded_inputs(image_tensor): def distorded_inputs(image_tensor):
......
...@@ -14,35 +14,22 @@ import tensorflow as tf ...@@ -14,35 +14,22 @@ import tensorflow as tf
import numpy as np import numpy as np
import skluc.mldatasets as dataset import skluc.mldatasets as dataset
from skluc.neural_networks import convolution_mnist, classification_mnist, batch_generator from skluc.neural_networks import convolution_mnist, classification_mnist, batch_generator
from fasfood_layer import fast_food from skluc.kernel_approximation.fasfood_layer import fast_food
tf.logging.set_verbosity(tf.logging.ERROR) tf.logging.set_verbosity(tf.logging.ERROR)
import time as t import time as t
from sklearn.preprocessing import LabelBinarizer
enc = LabelBinarizer()
mnist = dataset.MnistDataset()
mnist = mnist.load()
X_train, Y_train = mnist["train"]
X_train = np.array(X_train / 255)
enc.fit(Y_train)
Y_train = np.array(enc.transform(Y_train))
X_test, Y_test = mnist["test"]
X_test = np.array(X_test / 255)
Y_test = np.array(enc.transform(Y_test))
X_train = X_train.astype(np.float32)
permut = np.random.permutation(X_train.shape[0])
val_size = 5000 val_size = 5000
X_val = X_train[permut[:val_size]] mnist = dataset.MnistDataset(validation_size=val_size)
X_train = X_train[permut[val_size:]] mnist.load()
Y_val = Y_train[permut[:val_size]] mnist.normalize()
Y_train = Y_train[permut[val_size:]] mnist.to_one_hot()
X_test = X_test.astype(np.float32) mnist.data_astype(np.float32)
Y_train = Y_train.astype(np.float32) mnist.labels_astype(np.float32)
Y_test = Y_test.astype(np.float32) X_train, Y_train = mnist.train
X_test, Y_test = mnist.test
X_val, Y_val = mnist.validation
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -30,7 +30,7 @@ from skluc.neural_networks import inference_mnist, batch_generator, convolution_ ...@@ -30,7 +30,7 @@ from skluc.neural_networks import inference_mnist, batch_generator, convolution_
inference_cifar10, convolution_cifar, classification_cifar inference_cifar10, convolution_cifar, classification_cifar
import skluc.mldatasets as dataset import skluc.mldatasets as dataset
from fasfood_layer import fast_food from skluc.kernel_approximation.fasfood_layer import fast_food
import docopt import docopt
......
import numpy as np
import tensorflow as tf
import scipy.linalg
import scipy.stats
# --- Fast Food Naive --- #
def G_variable(shape, trainable=False):
"""
Return a Gaussian Random matrix converted into Tensorflow Variable.
:param shape: The shape of the matrix (number of fastfood stacks (v), dimension of the input space (d))
:type shape: int or tuple of int (tuple size = 2)
:return: tf.Variable object containing the matrix, The norm2 of each line (np.array of float)
"""
assert type(shape) == int or (type(shape) == tuple and len(shape) == 2)
G = np.random.normal(size=shape).astype(np.float32)
G_norms = np.linalg.norm(G, ord=2, axis=1)
return tf.Variable(G, name="G", trainable=trainable), G_norms
def B_variable(shape, trainable=False):
"""
Return a random matrix of -1 and 1 picked uniformly and converted into Tensorflow Variable.
:param shape: The shape of the matrix (number of fastfood stacks (v), dimension of the input space (d))
:type shape: int or tuple of int (tuple size = 2)
:return: tf.Variable object containing the matrix
"""
assert type(shape) == int or (type(shape) == tuple and len(shape) == 2)
B = np.random.choice([-1, 1], size=shape, replace=True).astype(np.float32)
return tf.Variable(B, name="B", trainable=trainable)
def P_variable(d, nbr_stack):
"""
Return a permutation matrix converted into Tensorflow Variable.
:param d: The width of the matrix (dimension of the input space)
:type d: int
:param nbr_stack: The height of the matrix (nbr_stack x d is the dimension of the output space)
:type nbr_stack: int
:return: tf.Variable object containing the matrix
"""
idx = np.hstack([(i * d) + np.random.permutation(d) for i in range(nbr_stack)])
P = np.random.permutation(np.eye(N=nbr_stack * d))[idx].astype(np.float32)
return tf.Variable(P, name="P", trainable=False)
def H_variable(d):
"""
Return an Hadamard matrix converted into Tensorflow Variable.
d must be a power of two.
:param d: The size of the Hadamard matrix (dimension of the input space).
:type d: int
:return: tf.Variable object containing the diagonal and not trainable
"""
H = build_hadamard(d).astype(np.float32)
return tf.Variable(H, name="H", trainable=False)
def S_variable(shape, G_norms, trainable=False):
"""
Return a scaling matrix of random values picked from a chi distribution.
The values are re-scaled using the norm of the associated Gaussian random matrix G. The associated Gaussian
vectors are the ones generated by the `G_variable` function.
:param shape: The shape of the matrix (number of fastfood stacks (v), dimension of the input space (d))
:type shape: int or tuple of int (tuple size = 2)
:param G_norms: The norms of the associated Gaussian random matrices G.
:type G_norms: np.array of floats
:return: tf.Variable object containing the matrix.
"""
S = np.multiply((1 / G_norms.reshape((-1, 1))), scipy.stats.chi.rvs(shape[1], size=shape).astype(np.float32))
return tf.Variable(S, name="S", trainable=trainable)
def fast_food(conv_out, sigma, nbr_stack=1, trainable=False):
"""
Return a fastfood transform op compatible with tensorflow graph.
Implementation largely inspired from https://gist.github.com/dougalsutherland/1a3c70e57dd1f64010ab .
See:
"Fastfood | Approximating Kernel Expansions in Loglinear Time" by
Quoc Le, Tamas Sarl and Alex Smola.
:param conv_out: the input of the op
:param sigma: bandwith of the gaussian distribution
:param nbr_stack: number of fast food stacks
:param trainable: the diagonal matrices are trainable or not
:return: the output of the fastfood transform
"""
with tf.name_scope("fastfood" + "_sigma-"+str(sigma)):
init_dim = np.prod([s.value for s in conv_out.shape if s.value is not None])
final_dim = int(dimensionality_constraints(init_dim))
padding = final_dim - init_dim
conv_out2 = tf.reshape(conv_out, [-1, init_dim])
paddings = tf.constant([[0, 0], [0, padding]])
conv_out2 = tf.pad(conv_out2, paddings, "CONSTANT")
G, G_norm = G_variable((nbr_stack, final_dim), trainable=trainable)
tf.summary.histogram("weights_G", G)
B = B_variable((nbr_stack, final_dim), trainable=trainable)
tf.summary.histogram("weights_B", B)
H = H_variable(final_dim)
tf.summary.histogram("weights_H", H)
P = P_variable(final_dim, nbr_stack)
tf.summary.histogram("weights_P", P)
S = S_variable((nbr_stack, final_dim), G_norm, trainable=trainable)
tf.summary.histogram("weights_S", S)
conv_out2 = tf.reshape(conv_out2, (1, -1, 1, final_dim))
h_ff1 = tf.multiply(conv_out2, B, name="Bx")
h_ff1 = tf.reshape(h_ff1, (-1, final_dim))
h_ff2 = tf.matmul(h_ff1, H, name="HBx")
h_ff2 = tf.reshape(h_ff2, (-1, final_dim * nbr_stack))
h_ff3 = tf.matmul(h_ff2, P, name="PHBx")
h_ff4 = tf.multiply(tf.reshape(h_ff3, (-1, final_dim * nbr_stack)), tf.reshape(G, (-1, final_dim * nbr_stack)), name="GPHBx")
h_ff4 = tf.reshape(h_ff4, (-1, final_dim))
h_ff5 = tf.matmul(h_ff4, H, name="HGPHBx")
h_ff6 = tf.scalar_mul((1/(sigma * np.sqrt(final_dim))), tf.multiply(tf.reshape(h_ff5, (-1, final_dim * nbr_stack)), tf.reshape(S, (-1, final_dim * nbr_stack)), name="SHGPHBx"))
h_ff7_1 = tf.cos(h_ff6)
h_ff7_2 = tf.sin(h_ff6)
h_ff7 = tf.scalar_mul(tf.sqrt(float(1 / final_dim)), tf.concat([h_ff7_1, h_ff7_2], axis=1))
return h_ff7
# todo ajouter ce module a scikit-luc
# --- Hadamard utils --- #
def dimensionality_constraints(d):
"""
Enforce d to be a power of 2
:param d: the original dimension
:return: the final dimension
"""
if not is_power_of_two(d):
# find d that fulfills 2^l
d = np.power(2, np.floor(np.log2(d)) + 1)
return d
def is_power_of_two(input_integer):
""" Test if an integer is a power of two. """
if input_integer == 1:
return False
return input_integer != 0 and ((input_integer & (input_integer - 1)) == 0)
def build_hadamard(n_neurons):
return scipy.linalg.hadamard(n_neurons)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment