Unit tests

parent d44b8012
...@@ -11,6 +11,8 @@ import bob.measure ...@@ -11,6 +11,8 @@ import bob.measure
from tensorflow.core.framework import summary_pb2 from tensorflow.core.framework import summary_pb2
from scipy.spatial.distance import cosine from scipy.spatial.distance import cosine
from bob.learn.tensorflow.datashuffler import Memory, Disk
class ExperimentAnalizer: class ExperimentAnalizer:
""" """
...@@ -55,35 +57,44 @@ class ExperimentAnalizer: ...@@ -55,35 +57,44 @@ class ExperimentAnalizer:
self.network = network self.network = network
self.session = session self.session = session
# Getting the base class. Recipe extracted from
# http://stackoverflow.com/questions/5516263/creating-an-object-from-a-base-class-object-in-python/5516330#5516330
if isinstance(data_shuffler, Memory):
base_data_shuffler = object.__new__(Memory)
base_data_shuffler.__dict__ = data_shuffler.__dict__.copy()
else:
base_data_shuffler = object.__new__(Disk)
base_data_shuffler.__dict__ = data_shuffler.__dict__.copy()
# Extracting features for enrollment # Extracting features for enrollment
enroll_data, enroll_labels = self.data_shuffler.get_batch() enroll_data, enroll_labels = base_data_shuffler.get_batch()
enroll_features = self.network(enroll_data, session=self.session) enroll_features = self.network(enroll_data, session=self.session)
del enroll_data del enroll_data
# Extracting features for probing # Extracting features for probing
probe_data, probe_labels = self.data_shuffler.get_batch() probe_data, probe_labels = base_data_shuffler.get_batch()
probe_features = self.network(probe_data, session=self.session) probe_features = self.network(probe_data, session=self.session)
del probe_data del probe_data
# Creating models # Creating models
models = [] models = []
for i in range(len(self.data_shuffler.possible_labels)): for i in range(len(base_data_shuffler.possible_labels)):
indexes_model = numpy.where(enroll_labels == self.data_shuffler.possible_labels[i])[0] indexes_model = numpy.where(enroll_labels == self.data_shuffler.possible_labels[i])[0]
models.append(numpy.mean(enroll_features[indexes_model, :], axis=0)) models.append(numpy.mean(enroll_features[indexes_model, :], axis=0))
# Probing # Probing
positive_scores = numpy.zeros(shape=0) positive_scores = numpy.zeros(shape=0)
negative_scores = numpy.zeros(shape=0) negative_scores = numpy.zeros(shape=0)
for i in range(len(self.data_shuffler.possible_labels)): for i in range(len(base_data_shuffler.possible_labels)):
#for i in self.data_shuffler.possible_labels: #for i in self.data_shuffler.possible_labels:
# Positive scoring # Positive scoring
indexes = probe_labels == self.data_shuffler.possible_labels[i] indexes = probe_labels == base_data_shuffler.possible_labels[i]
positive_data = probe_features[indexes, :] positive_data = probe_features[indexes, :]
p = [cosine(models[i], positive_data[j]) for j in range(positive_data.shape[0])] p = [cosine(models[i], positive_data[j]) for j in range(positive_data.shape[0])]
positive_scores = numpy.hstack((positive_scores, p)) positive_scores = numpy.hstack((positive_scores, p))
# negative scoring # negative scoring
indexes = probe_labels != self.data_shuffler.possible_labels[i] indexes = probe_labels != base_data_shuffler.possible_labels[i]
negative_data = probe_features[indexes, :] negative_data = probe_features[indexes, :]
n = [cosine(models[i], negative_data[j]) for j in range(negative_data.shape[0])] n = [cosine(models[i], negative_data[j]) for j in range(negative_data.shape[0])]
negative_scores = numpy.hstack((negative_scores, n)) negative_scores = numpy.hstack((negative_scores, n))
......
...@@ -80,7 +80,7 @@ class Disk(Base): ...@@ -80,7 +80,7 @@ class Disk(Base):
for i in range(self.batch_size): for i in range(self.batch_size):
file_name = self.data[indexes[i]] file_name = self.data[indexes[i]]
data = self.load_from_file(file_name, self.shape) data = self.load_from_file(file_name)
selected_data[i, ...] = data selected_data[i, ...] = data
if self.scale: if self.scale:
......
...@@ -68,8 +68,8 @@ class SiameseDisk(Siamese, Disk): ...@@ -68,8 +68,8 @@ class SiameseDisk(Siamese, Disk):
genuine = True genuine = True
for i in range(self.shape[0]): for i in range(self.shape[0]):
file_name, file_name_p = self.get_genuine_or_not(self.data, self.labels, genuine=genuine) file_name, file_name_p = self.get_genuine_or_not(self.data, self.labels, genuine=genuine)
data[i, ...] = self.load_from_file(str(file_name), self.shape) data[i, ...] = self.load_from_file(str(file_name))
data_p[i, ...] = self.load_from_file(str(file_name_p), self.shape) data_p[i, ...] = self.load_from_file(str(file_name_p))
labels_siamese[i] = not genuine labels_siamese[i] = not genuine
genuine = not genuine genuine = not genuine
......
...@@ -71,9 +71,9 @@ class TripletDisk(Triplet, Disk): ...@@ -71,9 +71,9 @@ class TripletDisk(Triplet, Disk):
for i in range(self.shape[0]): for i in range(self.shape[0]):
file_name_a, file_name_p, file_name_n = self.get_one_triplet(self.data, self.labels) file_name_a, file_name_p, file_name_n = self.get_one_triplet(self.data, self.labels)
data_a[i, ...] = self.load_from_file(str(file_name_a), self.shape) data_a[i, ...] = self.load_from_file(str(file_name_a))
data_p[i, ...] = self.load_from_file(str(file_name_p), self.shape) data_p[i, ...] = self.load_from_file(str(file_name_p))
data_n[i, ...] = self.load_from_file(str(file_name_n), self.shape) data_n[i, ...] = self.load_from_file(str(file_name_n))
if self.scale: if self.scale:
data_a *= self.scale_value data_a *= self.scale_value
......
...@@ -30,10 +30,19 @@ class Constant(Initialization): ...@@ -30,10 +30,19 @@ class Constant(Initialization):
def __call__(self, shape, name): def __call__(self, shape, name):
initializer = tf.constant(self.constant_value, shape=shape) initializer = tf.constant(self.constant_value, shape=shape)
if self.use_gpu: try:
with tf.device("/gpu:0"): with tf.variable_scope(name):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) if self.use_gpu:
else: with tf.device("/gpu:0"):
with tf.device("/cpu"): return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
except ValueError:
with tf.variable_scope(name, reuse=True):
if self.use_gpu:
with tf.device("/gpu:0"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
...@@ -36,11 +36,21 @@ class Gaussian(Initialization): ...@@ -36,11 +36,21 @@ class Gaussian(Initialization):
stddev=self.std, stddev=self.std,
seed=self.seed) seed=self.seed)
if self.use_gpu: try:
with tf.device("/gpu:0"): with tf.variable_scope(name):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) if self.use_gpu:
else: with tf.device("/gpu:0"):
with tf.device("/cpu"): return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
except ValueError:
with tf.variable_scope(name, reuse=True):
if self.use_gpu:
with tf.device("/gpu:0"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
...@@ -38,11 +38,20 @@ class SimplerXavier(Initialization): ...@@ -38,11 +38,20 @@ class SimplerXavier(Initialization):
initializer = tf.truncated_normal(shape, stddev=stddev, seed=self.seed) initializer = tf.truncated_normal(shape, stddev=stddev, seed=self.seed)
if self.use_gpu: try:
with tf.device("/gpu:0"): with tf.variable_scope(name):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) if self.use_gpu:
else: with tf.device("/gpu:0"):
with tf.device("/cpu"): return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
except ValueError:
with tf.variable_scope(name, reuse=True):
if self.use_gpu:
with tf.device("/gpu:0"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
...@@ -39,11 +39,20 @@ class Xavier(Initialization): ...@@ -39,11 +39,20 @@ class Xavier(Initialization):
initializer = tf.truncated_normal(shape, stddev=stddev, seed=self.seed) initializer = tf.truncated_normal(shape, stddev=stddev, seed=self.seed)
if self.use_gpu: try:
with tf.device("/gpu:0"): with tf.variable_scope(name):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) if self.use_gpu:
else: with tf.device("/gpu:0"):
with tf.device("/cpu"): return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
return tf.get_variable(name, initializer=initializer, dtype=tf.float32) else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
except ValueError:
with tf.variable_scope(name, reuse=True):
if self.use_gpu:
with tf.device("/gpu:0"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
else:
with tf.device("/cpu"):
return tf.get_variable(name, initializer=initializer, dtype=tf.float32)
...@@ -60,13 +60,13 @@ class MLP(SequenceNetwork): ...@@ -60,13 +60,13 @@ class MLP(SequenceNetwork):
for i in range(len(hidden_layers)): for i in range(len(hidden_layers)):
l = hidden_layers[i] l = hidden_layers[i]
self.add(FullyConnected(name="fc{0}".format(i), self.add(FullyConnected(name="mlp_fc{0}".format(i),
output_dim=l, output_dim=l,
activation=hidden_activation, activation=hidden_activation,
weights_initialization=weights_initialization, weights_initialization=weights_initialization,
bias_initialization=bias_initialization)) bias_initialization=bias_initialization))
self.add(FullyConnected(name="fc_output", self.add(FullyConnected(name="mlp_fc_output",
output_dim=output_shape, output_dim=output_shape,
activation=output_activation, activation=output_activation,
weights_initialization=weights_initialization, weights_initialization=weights_initialization,
......
...@@ -118,71 +118,6 @@ class SequenceNetwork(six.with_metaclass(abc.ABCMeta, object)): ...@@ -118,71 +118,6 @@ class SequenceNetwork(six.with_metaclass(abc.ABCMeta, object)):
return variables return variables
def save(self, hdf5, step=None):
"""Save the state of the network in HDF5 format
**Parameters**
hdf5: An opened :py:class:`bob.io.base.HDF5File`
step: The current training step. If not `None`, will create a HDF5 group with the current step.
"""
# Directory that stores the tensorflow variables
hdf5.create_group('/tensor_flow')
hdf5.cd('/tensor_flow')
if step is not None:
group_name = '/step_{0}'.format(step)
hdf5.create_group(group_name)
hdf5.cd(group_name)
# Iterating the variables of the model
for v in self.dump_variables().keys():
hdf5.set(v, self.dump_variables()[v].eval())
hdf5.cd('..')
if step is not None:
hdf5.cd('..')
hdf5.set('input_divide', self.input_divide)
hdf5.set('input_subtract', self.input_subtract)
def load(self, hdf5, shape, session=None):
"""Load the network
**Parameters**
hdf5: The saved network in the :py:class:`bob.io.base.HDF5File` format
shape: Input shape of the network
session: tensorflow `session <https://www.tensorflow.org/versions/r0.11/api_docs/python/client.html#Session>`_
"""
if session is None:
session = tf.Session()
# Loading the normalization parameters
self.input_divide = hdf5.read('input_divide')
self.input_subtract = hdf5.read('input_subtract')
# Loading variables
place_holder = tf.placeholder(tf.float32, shape=shape, name="load")
self.compute_graph(place_holder)
tf.initialize_all_variables().run(session=session)
hdf5.cd('/tensor_flow')
for k in self.sequence_net:
# TODO: IT IS NOT SMART TESTING ALONG THIS PAGE
if not isinstance(self.sequence_net[k], MaxPooling):
#self.sequence_net[k].W.assign(hdf5.read(self.sequence_net[k].W.name))
self.sequence_net[k].W.assign(hdf5.read(self.sequence_net[k].W.name)).eval(session=session)
session.run(self.sequence_net[k].W)
self.sequence_net[k].b.assign(hdf5.read(self.sequence_net[k].b.name)).eval(session=session)
session.run(self.sequence_net[k].b)
def variable_summaries(self, var, name): def variable_summaries(self, var, name):
"""Attach a lot of summaries to a Tensor.""" """Attach a lot of summaries to a Tensor."""
with tf.name_scope('summaries'): with tf.name_scope('summaries'):
...@@ -248,40 +183,113 @@ class SequenceNetwork(six.with_metaclass(abc.ABCMeta, object)): ...@@ -248,40 +183,113 @@ class SequenceNetwork(six.with_metaclass(abc.ABCMeta, object)):
# self.saver = tf.train.Saver(variables) # self.saver = tf.train.Saver(variables)
#self.saver.restore(session, path) #self.saver.restore(session, path)
def save(self, hdf5, step=None):
"""
Save the state of the network in HDF5 format
**Parameters**
hdf5: An opened :py:class:`bob.io.base.HDF5File`
step: The current training step. If not `None`, will create a HDF5 group with the current step.
"""
def create_groups(path):
split_path = path.split("/")
for i in range(0, len(split_path)-1):
p = split_path[i]
hdf5.create_group(p)
# Directory that stores the tensorflow variables
hdf5.create_group('/tensor_flow')
hdf5.cd('/tensor_flow')
if step is not None:
group_name = '/step_{0}'.format(step)
hdf5.create_group(group_name)
hdf5.cd(group_name)
# Iterating the variables of the model
for v in self.dump_variables().keys():
create_groups(v)
hdf5.set(v, self.dump_variables()[v].eval())
hdf5.cd('..')
if step is not None:
hdf5.cd('..')
hdf5.set('input_divide', self.input_divide)
hdf5.set('input_subtract', self.input_subtract)
def load(self, hdf5, shape, session=None):
"""
Load the network
**Parameters**
hdf5: The saved network in the :py:class:`bob.io.base.HDF5File` format
shape: Input shape of the network
session: tensorflow `session <https://www.tensorflow.org/versions/r0.11/api_docs/python/client.html#Session>`_
"""
if session is None:
session = tf.Session()
# Loading the normalization parameters
self.input_divide = hdf5.read('input_divide')
self.input_subtract = hdf5.read('input_subtract')
# Loading variables
place_holder = tf.placeholder(tf.float32, shape=shape, name="load")
self.compute_graph(place_holder)
tf.initialize_all_variables().run(session=session)
hdf5.cd('/tensor_flow')
for k in self.sequence_net:
# TODO: IT IS NOT SMART TESTING ALONG THIS PAGE
if not isinstance(self.sequence_net[k], MaxPooling):
#self.sequence_net[k].W.assign(hdf5.read(self.sequence_net[k].W.name))
self.sequence_net[k].W.assign(hdf5.read(self.sequence_net[k].W.name)).eval(session=session)
session.run(self.sequence_net[k].W)
self.sequence_net[k].b.assign(hdf5.read(self.sequence_net[k].b.name)).eval(session=session)
session.run(self.sequence_net[k].b)
""" """
def save(self, session, path, step=None): def save(self, session, path, step=None):
if self.saver is None: if self.saver is None:
variables = self.dump_variables() #variables = self.dump_variables()
variables['mean'] = tf.Variable(10.0) #variables['mean'] = tf.Variable(10.0)
#import ipdb; ipdb.set_trace() #import ipdb; ipdb.set_trace()
tf.initialize_all_variables().run() #tf.initialize_all_variables().run()
self.saver = tf.train.Saver(variables) self.saver = tf.train.Saver(session)
if step is None: if step is None:
return self.saver.save(session, os.path.join(path, "model.ckpt")) return self.saver.save(session, path)
else: else:
return self.saver.save(session, os.path.join(path, "model" + str(step) + ".ckpt")) return self.saver.save(session, path)
def load(self, path, shape, session=None): def load(self, path, session=None):
if session is None: if session is None:
session = tf.Session() session = tf.Session()
#tf.initialize_all_variables().run(session=session)
# Loading variables # Loading variables
place_holder = tf.placeholder(tf.float32, shape=shape, name="load") #place_holder = tf.placeholder(tf.float32, shape=shape, name="load")
self.compute_graph(place_holder) #self.compute_graph(place_holder)
tf.initialize_all_variables().run(session=session) #tf.initialize_all_variables().run(session=session)
if self.saver is None: #if self.saver is None:
variables = self.dump_variables() #variables = self.dump_variables()
variables['input_divide'] = self.input_divide #variables['input_divide'] = self.input_divide
variables['input_subtract'] = self.input_subtract #variables['input_subtract'] = self.input_subtract
self.saver = tf.train.Saver(variables) #self.saver = tf.train.Saver(variables)
self.saver.restore(session, path) self.saver.restore(session, path)
""" """
\ No newline at end of file
...@@ -22,12 +22,13 @@ from docopt import docopt ...@@ -22,12 +22,13 @@ from docopt import docopt
import tensorflow as tf import tensorflow as tf
from .. import util from .. import util
SEED = 10 SEED = 10
from bob.learn.tensorflow.data import MemoryDataShuffler, TextDataShuffler from bob.learn.tensorflow.datashuffler import SiameseMemory
from bob.learn.tensorflow.network import Lenet, MLP, LenetDropout, VGG, Chopra, Dummy from bob.learn.tensorflow.network import Lenet, MLP, LenetDropout, VGG, Chopra, Dummy
from bob.learn.tensorflow.trainers import SiameseTrainer from bob.learn.tensorflow.trainers import SiameseTrainer
from bob.learn.tensorflow.loss import ContrastiveLoss from bob.learn.tensorflow.loss import ContrastiveLoss
import numpy import numpy
def main(): def main():
args = docopt(__doc__, version='Mnist training with TensorFlow') args = docopt(__doc__, version='Mnist training with TensorFlow')
...@@ -39,105 +40,40 @@ def main(): ...@@ -39,105 +40,40 @@ def main():
perc_train = 0.9 perc_train = 0.9
# Loading data # Loading data
mnist = True
if mnist:
train_data, train_labels, validation_data, validation_labels = \
util.load_mnist(data_dir="./src/bob.db.mnist/bob/db/mnist/")
train_data = numpy.reshape(train_data, (train_data.shape[0], 28, 28, 1))
validation_data = numpy.reshape(validation_data, (validation_data.shape[0], 28, 28, 1))
train_data_shuffler = MemoryDataShuffler(train_data, train_labels, train_data, train_labels, validation_data, validation_labels = \
input_shape=[28, 28, 1], util.load_mnist(data_dir="./src/bob.db.mnist/bob/db/mnist/")
scale=True, train_data = numpy.reshape(train_data, (train_data.shape[0], 28, 28, 1))
batch_size=BATCH_SIZE) validation_data = numpy.reshape(validation_data, (validation_data.shape[0], 28, 28, 1))
validation_data_shuffler = MemoryDataShuffler(validation_data, validation_labels, train_data_shuffler = SiameseMemory(train_data, train_labels,
input_shape=[28, 28, 1], input_shape=[28, 28, 1],
scale=True, scale=True,
batch_size=VALIDATION_BATCH_SIZE) batch_size=BATCH_SIZE)
else: validation_data_shuffler = SiameseMemory(validation_data, validation_labels,
import bob.db.mobio input_shape=[28, 28, 1],
db_mobio = bob.db.mobio.Database() scale=True,
batch_size=VALIDATION_BATCH_SIZE)
import bob.db.casia_webface
db_casia = bob.db.casia_webface.Database()
# Preparing train set
train_objects = db_casia.objects(groups="world")
#train_objects = db.objects(groups="world")
train_labels = [int(o.client_id) for o in train_objects]
directory = "/idiap/resource/database/CASIA-WebFace/CASIA-WebFace"
train_file_names = [o.make_path(
directory=directory,
extension="")
for o in train_objects]
#import ipdb;
#ipdb.set_trace();
#train_file_names = [o.make_path(
# directory="/idiap/group/biometric/databases/orl",
# extension=".pgm")
# for o in train_objects]
train_data_shuffler = TextDataShuffler(train_file_names, train_labels,
input_shape=[250, 250, 3],
batch_size=BATCH_SIZE)
#train_data_shuffler = TextDataShuffler(train_file_names, train_labels,
# input_shape=[56, 46, 1],
# batch_size=BATCH_SIZE)
# Preparing train set
directory = "/idiap/temp/tpereira/DEEP_FACE/CASIA/preprocessed"
validation_objects = db_mobio.objects(protocol="male", groups="dev")
validation_labels = [o.client_id for o in validation_objects]
#validation_file_names = [o.make_path(
# directory="/idiap/group/biometric/databases/orl",
# extension=".pgm")
# for o in validation_objects]
validation_file_names = [o.make_path(
directory=directory,
extension=".hdf5")
for o in validation_objects]
validation_data_shuffler = TextDataShuffler(validation_file_names, validation_labels,
input_shape=[250, 250, 3],
batch_size=VALIDATION_BATCH_SIZE)
#validation_data_shuffler = TextDataShuffler(validation_file_names, validation_labels,
# input_shape=[56, 46, 1],
# batch_size=VALIDATION_BATCH_SIZE)
# Preparing the architecture # Preparing the architecture
n_classes = len(train_data_shuffler.possible_labels) n_classes = len(train_data_shuffler.possible_labels)
#n_classes = 50
cnn = True cnn = True
if cnn: if cnn:
# LENET PAPER CHOPRA # LENET PAPER CHOPRA
architecture = Chopra(seed=SEED, fc1_output=n_classes) architecture = Chopra(seed=SEED, fc1_output=n_classes)
#architecture = Lenet(default_feature_layer="fc2", n_classes=n_classes, conv1_output=8, conv2_output=16,use_gpu=USE_GPU)
#architecture = VGG(n_classes=n_classes, use_gpu=USE_GPU)
#architecture = Dummy(seed=SEED)
#architecture = LenetDropout(default_feature_layer="fc2", n_classes=n_classes, conv1_output=4, conv2_output=8, use_gpu=USE_GPU)
loss = ContrastiveLoss(contrastive_margin=4.) loss = ContrastiveLoss(contrastive_margin=4.)
optimizer = tf.train.GradientDescentOptimizer(0.000001) #optimizer = tf.train.GradientDescentOptimizer(0.000001)
trainer = SiameseTrainer(architecture=architecture, trainer = SiameseTrainer(architecture=architecture,
loss=loss, loss=loss,
iterations=ITERATIONS, iterations=ITERATIONS,
snapshot=VALIDATION_TEST, snapshot=VALIDATION_TEST,
optimizer=optimizer, prefetch=False,
prefetch=True,
temp_dir="./LOGS/siamese-cnn-prefetch") temp_dir="./LOGS/siamese-cnn-prefetch")
#import ipdb; ipdb.set_trace();
trainer.train(train_data_shuffler, validation_data_shuffler) trainer.train(train_data_shuffler, validation_data_shuffler)
#trainer.train(train_data_shuffler)
else: else:
mlp = MLP(n_classes, hidden_layers=[15, 20]) mlp = MLP(n_classes, hidden_layers=[15, 20])
......
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# @author: Tiago de Freitas Pereira <tiago.pereira@idiap.ch>
# @date: Thu 13 Oct 2016 13:35 CEST
import numpy
from bob.learn.tensorflow.datashuffler import Memory, SiameseMemory, TripletMemory, Disk, SiameseDisk, TripletDisk
from bob.learn.tensorflow.network import