Commit d8b85d54 authored by Tiago de Freitas Pereira's avatar Tiago de Freitas Pereira

Merge branch 'updates' into 'master'

Updates

See merge request !15
parents 9f6a3721 171ede05
Pipeline #12908 passed with stages
in 14 minutes and 35 seconds
......@@ -260,5 +260,6 @@ def inception_resnet_v2(inputs, is_training=True,
net = slim.fully_connected(net, bottleneck_layer_size, activation_fn=None,
scope='Bottleneck', reuse=False)
return net, end_points
#!/usr/bin/env python
"""Script that converts bob.db.lfw database to TF records
Usage:
%(prog)s <data-path> <output-file> [--extension=<arg> --protocol=<arg> --verbose]
%(prog)s --help
%(prog)s --version
Options:
-h --help show this help message and exit
<data-path> Path that contains the features
--extension=<arg> Default feature extension [default: .hdf5]
--protocol=<arg> One of the LFW protocols [default: view1]
The possible protocol options are the following:
'view1', 'fold1', 'fold2', 'fold3', 'fold4', 'fold5', 'fold6', 'fold7', 'fold8', 'fold9', 'fold10'
More details about our interface to LFW database can be found in
https://www.idiap.ch/software/bob/docs/bob/bob.db.lfw/master/index.html.
"""
import tensorflow as tf
from bob.io.base import create_directories_safe
from bob.bio.base.utils import load, read_config_file
from bob.core.log import setup, set_verbosity_level
import bob.db.lfw
import os
import bob.io.image
import bob.io.base
logger = setup(__name__)
def _bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def file_to_label(client_ids, f):
return client_ids[str(f.client_id)]
def get_pairs(all_pairs, match=True):
pairs = []
for p in all_pairs:
if p.is_match == match:
pairs.append(p.enroll_file)
pairs.append(p.probe_file)
return pairs
def main(argv=None):
from docopt import docopt
args = docopt(__doc__, version='')
data_path = args['<data-path>']
output_file = args['<output-file>']
extension = args['--extension']
protocol = args['--protocol']
#Setting the reader
reader = bob.io.base.load
# Sets-up logging
if args['--verbose']:
verbosity = 2
set_verbosity_level(logger, verbosity)
# Loading LFW models
database = bob.db.lfw.Database()
all_pairs = get_pairs(database.pairs(protocol=protocol), match=True)
client_ids = list(set([f.client_id for f in all_pairs]))
client_ids = dict(zip(client_ids, range(len(client_ids))))
create_directories_safe(os.path.dirname(output_file))
n_files = len(all_pairs)
with tf.python_io.TFRecordWriter(output_file) as writer:
for i, f in enumerate(all_pairs):
logger.info('Processing file %d out of %d', i + 1, n_files)
path = f.make_path(data_path, extension)
data = reader(path).astype('float32').tostring()
feature = {'train/data': _bytes_feature(data),
'train/label': _int64_feature(file_to_label(client_ids, f))}
example = tf.train.Example(features=tf.train.Features(feature=feature))
writer.write(example.SerializeToString())
if __name__ == '__main__':
main()
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# @author: Tiago de Freitas Pereira <tiago.pereira@idiap.ch>
"""
Load and debug tensorflow models
Usage:
load_and_debug.py <configuration> <output-dir>
load_and_debug.py -h | --help
Options:
-h --help Show this screen.
"""
from docopt import docopt
import bob.io.base
import os
import numpy
import imp
import bob.learn.tensorflow
import tensorflow as tf
import logging
logger = logging.getLogger("bob.learn")
def main():
args = docopt(__doc__, version='Mnist training with TensorFlow')
output_dir = args['<output-dir>']
config = imp.load_source('config', args['<configuration>'])
# Cleaning all variables in case you are loading the checkpoint
tf.reset_default_graph() if os.path.exists(output_dir) else None
logger.info("Directory already exists, trying to get the last checkpoint")
trainer = config.Trainer(config.train_data_shuffler,
iterations=0,
analizer=None,
temp_dir=output_dir)
trainer.create_network_from_file(output_dir)
import ipdb; ipdb.set_trace();
debug=True
......@@ -87,22 +87,34 @@ def main():
trainer.create_network_from_file(output_dir)
else:
# Preparing the architecture
input_pl = config.train_data_shuffler("data", from_queue=False)
if isinstance(trainer, bob.learn.tensorflow.trainers.SiameseTrainer):
graph = dict()
graph['left'] = config.architecture(input_pl['left'])
graph['right'] = config.architecture(input_pl['right'], reuse=True)
elif isinstance(trainer, bob.learn.tensorflow.trainers.TripletTrainer):
graph = dict()
graph['anchor'] = config.architecture(input_pl['anchor'])
graph['positive'] = config.architecture(input_pl['positive'], reuse=True)
graph['negative'] = config.architecture(input_pl['negative'], reuse=True)
# Either bootstrap from scratch or take the pointer directly from the config script
train_graph = None
validation_graph = None
if hasattr(config, 'train_graph'):
train_graph = config.train_graph
if hasattr(config, 'validation_graph'):
validation_graph = config.validation_graph
else:
graph = config.architecture(input_pl)
trainer.create_network_from_scratch(graph, loss=config.loss,
# Preparing the architecture
input_pl = config.train_data_shuffler("data", from_queue=False)
if isinstance(trainer, bob.learn.tensorflow.trainers.SiameseTrainer):
train_graph = dict()
train_graph['left'] = config.architecture(input_pl['left'])
train_graph['right'] = config.architecture(input_pl['right'], reuse=True)
elif isinstance(trainer, bob.learn.tensorflow.trainers.TripletTrainer):
train_graph = dict()
train_graph['anchor'] = config.architecture(input_pl['anchor'])
train_graph['positive'] = config.architecture(input_pl['positive'], reuse=True)
train_graph['negative'] = config.architecture(input_pl['negative'], reuse=True)
else:
train_graph = config.architecture(input_pl)
trainer.create_network_from_scratch(train_graph,
validation_graph=validation_graph,
loss=config.loss,
learning_rate=config.learning_rate,
optimizer=config.optimizer)
trainer.train()
......
......@@ -45,6 +45,33 @@ def scratch_network(train_data_shuffler, reuse=False):
return graph
def scratch_network_embeding_example(train_data_shuffler, reuse=False, get_embedding=False):
if isinstance(train_data_shuffler, tf.Tensor):
inputs = train_data_shuffler
else:
inputs = train_data_shuffler("data", from_queue=False)
# Creating a random network
initializer = tf.contrib.layers.xavier_initializer(seed=seed)
graph = slim.conv2d(inputs, 10, [3, 3], activation_fn=tf.nn.relu, stride=1, scope='conv1',
weights_initializer=initializer, reuse=reuse)
graph = slim.max_pool2d(graph, [4, 4], scope='pool1')
graph = slim.flatten(graph, scope='flatten1')
graph = slim.fully_connected(graph, 30, activation_fn=None, scope='fc1',
weights_initializer=initializer, reuse=reuse)
if get_embedding:
graph = tf.nn.l2_normalize(graph, dim=1, name="embedding")
else:
graph = slim.fully_connected(graph, 10, activation_fn=None, scope='logits',
weights_initializer=initializer, reuse=reuse)
return graph
def validate_network(embedding, validation_data, validation_labels, input_shape=[None, 28, 28, 1], normalizer=ScaleFactor()):
# Testing
validation_data_shuffler = Memory(validation_data, validation_labels,
......@@ -104,7 +131,7 @@ def test_cnn_trainer_scratch():
assert len(tf.global_variables())==0
def test_cnn_trainer_scratch_tfrecord():
def test_cnn_tfrecord():
tf.reset_default_graph()
train_data, train_labels, validation_data, validation_labels = load_mnist()
......@@ -201,3 +228,101 @@ def test_cnn_trainer_scratch_tfrecord():
assert len(tf.global_variables())==0
def test_cnn_tfrecord_embedding_validation():
tf.reset_default_graph()
train_data, train_labels, validation_data, validation_labels = load_mnist()
train_data = train_data.astype("float32") * 0.00390625
validation_data = validation_data.astype("float32") * 0.00390625
def _bytes_feature(value):
return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def create_tf_record(tfrecords_filename, data, labels):
writer = tf.python_io.TFRecordWriter(tfrecords_filename)
#for i in range(train_data.shape[0]):
for i in range(6000):
img = data[i]
img_raw = img.tostring()
feature = {'train/data': _bytes_feature(img_raw),
'train/label': _int64_feature(labels[i])
}
example = tf.train.Example(features=tf.train.Features(feature=feature))
writer.write(example.SerializeToString())
writer.close()
tf.reset_default_graph()
# Creating the tf record
tfrecords_filename = "mnist_train.tfrecords"
create_tf_record(tfrecords_filename, train_data, train_labels)
filename_queue = tf.train.string_input_producer([tfrecords_filename], num_epochs=55, name="input")
tfrecords_filename_val = "mnist_validation.tfrecords"
create_tf_record(tfrecords_filename_val, validation_data, validation_labels)
filename_queue_val = tf.train.string_input_producer([tfrecords_filename_val], num_epochs=55, name="input_validation")
# Creating the CNN using the TFRecord as input
train_data_shuffler = TFRecord(filename_queue=filename_queue,
batch_size=batch_size)
validation_data_shuffler = TFRecord(filename_queue=filename_queue_val,
batch_size=2000)
graph = scratch_network_embeding_example(train_data_shuffler)
validation_graph = scratch_network_embeding_example(validation_data_shuffler, reuse=True, get_embedding=True)
# Setting the placeholders
# Loss for the softmax
loss = MeanSoftMaxLoss()
# One graph trainer
trainer = Trainer(train_data_shuffler,
validation_data_shuffler=validation_data_shuffler,
validate_with_embeddings=True,
iterations=iterations, #It is supper fast
analizer=None,
temp_dir=directory)
learning_rate = constant(0.01, name="regular_lr")
trainer.create_network_from_scratch(graph=graph,
validation_graph=validation_graph,
loss=loss,
learning_rate=learning_rate,
optimizer=tf.train.GradientDescentOptimizer(learning_rate),
)
trainer.train()
os.remove(tfrecords_filename)
os.remove(tfrecords_filename_val)
assert True
tf.reset_default_graph()
del trainer
assert len(tf.global_variables())==0
# Inference. TODO: Wrap this in a package
file_name = os.path.join(directory, "model.ckp.meta")
images = tf.placeholder(tf.float32, shape=(None, 28, 28, 1))
graph = scratch_network_embeding_example(images, reuse=False)
session = tf.Session()
session.run(tf.global_variables_initializer())
saver = tf.train.import_meta_graph(file_name, clear_devices=True)
saver.restore(session, tf.train.latest_checkpoint(os.path.dirname("./temp/cnn_scratch/")))
data = numpy.random.rand(2, 28, 28, 1).astype("float32")
assert session.run(graph, feed_dict={images: data}).shape == (2, 10)
tf.reset_default_graph()
shutil.rmtree(directory)
assert len(tf.global_variables())==0
......@@ -62,3 +62,4 @@ def test_train_script_siamese():
tf.reset_default_graph()
assert len(tf.global_variables()) == 0
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# @author: Tiago de Freitas Pereira <tiago.pereira@idiap.ch>
import numpy
from bob.learn.tensorflow.utils import compute_embedding_accuracy
"""
Some unit tests for the datashuffler
"""
def test_embedding_accuracy():
numpy.random.seed(10)
samples_per_class = 5
class_a = numpy.random.normal(loc=0, scale=0.1, size=(samples_per_class, 2))
labels_a = numpy.zeros(samples_per_class)
class_b = numpy.random.normal(loc=10, scale=0.1, size=(samples_per_class, 2))
labels_b = numpy.ones(samples_per_class)
data = numpy.vstack((class_a, class_b))
labels = numpy.concatenate((labels_a, labels_b))
assert compute_embedding_accuracy(data, labels) == 1.
# Adding noise
noise = numpy.random.normal(loc=0, scale=0.1, size=(samples_per_class, 2))
noise_labels = numpy.ones(samples_per_class)
data = numpy.vstack((data, noise))
labels = numpy.concatenate((labels, noise_labels))
assert compute_embedding_accuracy(data, labels) == 10 / 15.
......@@ -121,6 +121,7 @@ class SiameseTrainer(Trainer):
def create_network_from_scratch(self,
graph,
validation_graph=None,
optimizer=tf.train.AdamOptimizer(),
loss=None,
......
......@@ -13,6 +13,7 @@ from tensorflow.core.framework import summary_pb2
import time
from bob.learn.tensorflow.datashuffler import OnlineSampling, TFRecord
from bob.learn.tensorflow.utils.session import Session
from bob.learn.tensorflow.utils import compute_embedding_accuracy
from .learning_rate import constant
import time
......@@ -54,11 +55,12 @@ class Trainer(object):
def __init__(self,
train_data_shuffler,
validation_data_shuffler=None,
validate_with_embeddings=False,
###### training options ##########
iterations=5000,
snapshot=500,
validation_snapshot=100,
snapshot=1000,
validation_snapshot=2000,
keep_checkpoint_every_n_hours=2,
## Analizer
......@@ -100,7 +102,8 @@ class Trainer(object):
self.loss = None
self.predictor = None
self.validation_predictor = None
self.validation_predictor = None
self.validate_with_embeddings = validate_with_embeddings
self.optimizer_class = None
self.learning_rate = None
......@@ -168,7 +171,10 @@ class Trainer(object):
# Running validation
if self.validation_data_shuffler is not None and step % self.validation_snapshot == 0:
self.compute_validation(step)
if self.validate_with_embeddings:
self.compute_validation_embeddings(step)
else:
self.compute_validation(step)
# Taking snapshot
if step % self.snapshot == 0:
......@@ -178,7 +184,11 @@ class Trainer(object):
# Running validation for the last time
if self.validation_data_shuffler is not None:
self.compute_validation(step)
if self.validate_with_embeddings:
self.compute_validation_embeddings(step)
else:
self.compute_validation(step)
logger.info("Training finally finished")
......@@ -264,7 +274,10 @@ class Trainer(object):
self.validation_graph = validation_graph
self.validation_predictor = self.loss(self.validation_graph, self.validation_label_ph)
if self.validate_with_embeddings:
self.validation_predictor = self.validation_graph
else:
self.validation_predictor = self.loss(self.validation_graph, self.validation_label_ph)
self.summaries_validation = self.create_general_summary(self.validation_predictor, self.validation_graph, self.validation_label_ph)
tf.add_to_collection("summaries_validation", self.summaries_validation)
......@@ -398,6 +411,30 @@ class Trainer(object):
logger.info("Loss VALIDATION set step={0} = {1}".format(step, l))
self.validation_summary_writter.add_summary(summary, step)
def compute_validation_embeddings(self, step):
"""
Computes the loss in the validation set with embeddings
** Parameters **
session: Tensorflow session
data_shuffler: The data shuffler to be used
step: Iteration number
"""
if self.validation_data_shuffler.prefetch:
embedding, labels = self.session.run([self.validation_predictor, self.validation_label_ph])
else:
feed_dict = self.get_feed_dict(self.validation_data_shuffler)
embedding, labels = self.session.run([self.validation_predictor, self.validation_label_ph],
feed_dict=feed_dict)
accuracy = compute_embedding_accuracy(embedding, labels)
summary = summary_pb2.Summary.Value(tag="accuracy", simple_value=accuracy)
logger.info("VALIDATION Accuracy set step={0} = {1}".format(step, accuracy))
self.validation_summary_writter.add_summary(summary_pb2.Summary(value=[summary]), step)
def create_general_summary(self, average_loss, output, label):
"""
Creates a simple tensorboard summary with the value of the loss and learning rate
......
......@@ -122,6 +122,7 @@ class TripletTrainer(Trainer):
def create_network_from_scratch(self,
graph,
validation_graph=None,
optimizer=tf.train.AdamOptimizer(),
loss=None,
......
......@@ -208,4 +208,28 @@ def debug_embbeding(image, architecture, embbeding_dim=2, feature_layer="fc3"):
embeddings[i] = embedding
return embeddings
def compute_embedding_accuracy(embedding, labels):
"""
Compute the accuracy through exhaustive comparisons between the embeddings
"""
from scipy.spatial.distance import cdist
distances = cdist(embedding, embedding)
n_samples = embedding.shape[0]
# Computing the argmin excluding comparisons with the same samples
# Basically, we are excluding the main diagonal
valid_indexes = distances[distances>0].reshape(n_samples, n_samples-1).argmin(axis=1)
# Getting the original positions of the indexes in the 1-axis
corrected_indexes = [ i if i<j else i+1 for i, j in zip(valid_indexes, range(n_samples))]
matching = [ labels[i]==labels[j] for i,j in zip(range(n_samples), corrected_indexes)]
accuracy = sum(matching)/float(n_samples)
return accuracy
......@@ -50,6 +50,8 @@ setup(
'compute_statistics.py = bob.learn.tensorflow.script.compute_statistics:main',
'train.py = bob.learn.tensorflow.script.train:main',
'bob_db_to_tfrecords = bob.learn.tensorflow.script.db_to_tfrecords:main',
'load_and_debug.py = bob.learn.tensorflow.script.load_and_debug:main',
'lfw_db_to_tfrecords.py = bob.learn.tensorflow.script.lfw_db_to_tfrecords:main'
],
},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment